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;
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.List;
17 import org.opendaylight.groupbasedpolicy.sf.classifiers.IpProtoClassifierDefinition;
18 import org.opendaylight.groupbasedpolicy.sf.classifiers.L4ClassifierDefinition;
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.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValue;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
34 * Match against TCP or UDP, and source and/or destination ports
36 public class L4Classifier extends Classifier {
38 protected L4Classifier(Classifier parent) {
43 public ClassifierDefinitionId getId() {
44 return L4ClassifierDefinition.ID;
48 public ClassifierDefinition getClassDef() {
49 return L4ClassifierDefinition.DEFINITION;
53 protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
54 validatePortParam(params, L4ClassifierDefinition.SRC_PORT_PARAM, L4ClassifierDefinition.SRC_PORT_RANGE_PARAM);
55 validatePortParam(params, L4ClassifierDefinition.DST_PORT_PARAM, L4ClassifierDefinition.DST_PORT_RANGE_PARAM);
56 validateRange(params, L4ClassifierDefinition.SRC_PORT_RANGE_PARAM);
57 validateRange(params, L4ClassifierDefinition.DST_PORT_RANGE_PARAM);
60 private void validatePortParam(Map<String, ParameterValue> params, String portParam, String portRangeParam) {
61 if (params.get(portParam) != null) {
62 StringBuilder paramLog = new StringBuilder();
63 if (params.get(portParam).getIntValue() == null) {
64 paramLog.append("Value of ")
66 .append(" parameter is not specified.");
67 throw new IllegalArgumentException(paramLog.toString());
69 if(params.get(portRangeParam) != null) {
70 paramLog.append("Source port parameters ")
73 .append(portRangeParam)
74 .append(" are mutually exclusive.");
75 throw new IllegalArgumentException(paramLog.toString());
80 private void validateRange(Map<String, ParameterValue> params, String portRangeParam) {
81 if (params.get(portRangeParam) != null) {
82 validateRangeValue(params.get(portRangeParam).getRangeValue());
86 private void validateRangeValue(RangeValue rangeValueParam) {
87 if (rangeValueParam == null) {
88 throw new IllegalArgumentException("Range parameter is specifiet but value is not present.");
90 final Long min = rangeValueParam.getMin();
91 final Long max = rangeValueParam.getMax();
93 throw new IllegalArgumentException("Range value mismatch. " + min + " is greater than MAX " + max + ".");
98 public List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
99 Set<Long> sPorts = new HashSet<>();
100 Set<Long> dPorts = new HashSet<>();
101 addToPortSet(params, L4ClassifierDefinition.SRC_PORT_PARAM, L4ClassifierDefinition.SRC_PORT_RANGE_PARAM, sPorts);
102 addToPortSet(params, L4ClassifierDefinition.DST_PORT_PARAM, L4ClassifierDefinition.DST_PORT_RANGE_PARAM, dPorts);
103 List<MatchBuilder> newMatches = new ArrayList<>();
104 for (MatchBuilder matchBuilder : matches) {
105 Layer4Match l4Match = matchBuilder.getLayer4Match();
106 Set<? extends Layer4Match> l4Matches = null;
107 if (l4Match == null) {
108 l4Match = resolveL4Match(params);
110 l4Matches = createL4Matches(l4Match, sPorts, dPorts);
111 for (Layer4Match newL4Match : l4Matches) {
112 newMatches.add(new MatchBuilder(matchBuilder.build()).setLayer4Match(newL4Match));
118 private void addToPortSet(Map<String, ParameterValue> params, String portParam, String portRangeParam, Set<Long> portSet) {
119 if (params.get(portParam) != null) {
120 portSet.add(params.get(portParam).getIntValue());
121 } else if (params.get(portRangeParam) != null) {
122 portSet.addAll(createSetFromRange(params.get(portRangeParam).getRangeValue()));
126 private Layer4Match resolveL4Match(Map<String, ParameterValue> params) {
127 Long ipProto = IpProtoClassifier.getIpProtoValue(params);
128 if (ipProto == null) {
129 throw new IllegalArgumentException("Parameter " + IpProtoClassifierDefinition.PROTO_PARAM + " is missing.");
131 if (IpProtoClassifierDefinition.UDP_VALUE.equals(ipProto)) {
132 return new UdpMatchBuilder().build();
133 } else if (IpProtoClassifierDefinition.TCP_VALUE.equals(ipProto)) {
134 return new TcpMatchBuilder().build();
135 } else if (IpProtoClassifierDefinition.SCTP_VALUE.equals(ipProto)) {
136 return new SctpMatchBuilder().build();
138 throw new IllegalArgumentException("Parameter " + IpProtoClassifierDefinition.PROTO_PARAM + ": value " + ipProto
139 + " is not supported.");
142 private Set<Long> createSetFromRange(RangeValue rangeValueParam) {
143 Set<Long> res = new HashSet<>();
144 if (rangeValueParam != null) {
145 final Long min = rangeValueParam.getMin();
146 final Long max = rangeValueParam.getMax();
147 for (long val = min; val <= max; val++) {
154 private Set<? extends Layer4Match> createL4Matches(Layer4Match l4Match, Set<Long> sPorts, Set<Long> dPorts) {
155 Set<? extends Layer4Match> l4Matches = null;
156 if (l4Match instanceof UdpMatch) {
157 l4Matches = createUdpMatches((UdpMatch) l4Match, sPorts, dPorts);
158 } else if (l4Match instanceof TcpMatch) {
159 l4Matches = createTcpMatches((TcpMatch) l4Match, sPorts, dPorts);
160 } else if (l4Match instanceof SctpMatch) {
161 l4Matches = createSctpMatches((SctpMatch) l4Match, sPorts, dPorts);
166 private Set<UdpMatch> createUdpMatches(UdpMatch udpMatch, Set<Long> sPorts, Set<Long> dPorts) {
167 Set<UdpMatch> udpMatches = new HashSet<>();
168 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
169 for (Long srcPort : sPorts) {
170 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
171 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue())).build());
173 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
174 for (Long dstPort : dPorts) {
175 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
176 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpDestinationPort(new PortNumber(dstPort.intValue()))
179 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
180 for (Long srcPort : sPorts) {
181 for (Long dstPort : dPorts) {
182 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
183 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
184 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue()))
185 .setUdpDestinationPort(new PortNumber(dstPort.intValue()))
193 private Set<TcpMatch> createTcpMatches(TcpMatch tcpMatch, Set<Long> sPorts, Set<Long> dPorts) {
194 Set<TcpMatch> tcpMatches = new HashSet<>();
195 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
196 for (Long srcPort : sPorts) {
197 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
198 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue())).build());
200 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
201 for (Long dstPort : dPorts) {
202 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
203 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpDestinationPort(new PortNumber(dstPort.intValue()))
206 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
207 for (Long srcPort : sPorts) {
208 for (Long dstPort : dPorts) {
209 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
210 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
211 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue()))
212 .setTcpDestinationPort(new PortNumber(dstPort.intValue()))
220 private Set<SctpMatch> createSctpMatches(SctpMatch sctpMatch, Set<Long> sPorts, Set<Long> dPorts) {
221 Set<SctpMatch> sctpMatches = new HashSet<>();
222 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
223 for (Long srcPort : sPorts) {
224 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
225 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
228 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
229 for (Long dstPort : dPorts) {
230 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
231 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpDestinationPort(new PortNumber(dstPort.intValue()))
234 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
235 for (Long srcPort : sPorts) {
236 for (Long dstPort : dPorts) {
237 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
238 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
239 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
240 .setSctpDestinationPort(new PortNumber(dstPort.intValue()))
248 private void equalOrNotSetValidation(PortNumber portInMatch, long paramValue) {
249 if (portInMatch != null) {
250 if (paramValue != portInMatch.getValue().longValue()) {
251 throw new IllegalArgumentException("Classification conflict detected for port values "
252 + portInMatch.getValue().longValue() + " and " + paramValue + ". It is not allowed "
253 + "to assign different values to the same parameter among all the classifiers within one rule.");
259 public void checkPrereqs(List<MatchBuilder> matches) {
260 for (MatchBuilder match : matches) {
263 proto = Long.valueOf(match.getIpMatch().getIpProtocol().longValue());
264 } catch (NullPointerException e) {
265 throw new IllegalArgumentException("Parameter " + IpProtoClassifierDefinition.PROTO_PARAM + " is missing.");
267 if (!IpProtoClassifierDefinition.TCP_VALUE.equals(proto) && !IpProtoClassifierDefinition.UDP_VALUE.equals(proto)
268 && !IpProtoClassifierDefinition.SCTP_VALUE.equals(proto)) {
269 throw new IllegalArgumentException("Value of parameter " + IpProtoClassifierDefinition.PROTO_PARAM
270 + " is not supported.");