2 * Copyright (c) 2015 CableLabs 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.controller.packetcable.provider;
11 import static com.google.common.base.Preconditions.checkNotNull;
13 import com.google.common.collect.Lists;
14 import java.net.Inet4Address;
15 import java.net.Inet6Address;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18 import java.util.List;
19 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ServiceFlowDirection;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.TosByte;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.attributes.AmId;
22 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.classifier.attributes.classifiers.ClassifierContainer;
23 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.classifier.attributes.classifiers.classifier.container.ClassifierChoice;
24 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.classifier.attributes.classifiers.classifier.container.classifier.choice.ExtClassifierChoice;
25 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.classifier.attributes.classifiers.classifier.container.classifier.choice.Ipv6ClassifierChoice;
26 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.classifier.attributes.classifiers.classifier.container.classifier.choice.QosClassifierChoice;
27 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.classifier.Classifier;
28 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.ext.classifier.ExtClassifier;
29 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gate.spec.GateSpec;
30 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.ipv6.classifier.Ipv6Classifier;
31 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.traffic.profile.TrafficProfile;
32 import org.pcmm.gates.IClassifier;
33 import org.pcmm.gates.IClassifier.Protocol;
34 import org.pcmm.gates.IExtendedClassifier;
35 import org.pcmm.gates.IExtendedClassifier.ActivationState;
36 import org.pcmm.gates.IGateSpec.Direction;
37 import org.pcmm.gates.IIPv6Classifier.FlowLabel;
38 import org.pcmm.gates.ITrafficProfile;
39 import org.pcmm.gates.impl.AMID;
40 import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
41 import org.pcmm.gates.impl.GateID;
42 import org.pcmm.gates.impl.PCMMError;
43 import org.pcmm.gates.impl.PCMMGateReq;
44 import org.pcmm.gates.impl.SubscriberID;
45 import org.pcmm.gates.impl.TransactionID;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * Build PCMM gate requests from API QoS Gate objects
52 public class PCMMGateReqBuilder {
54 private final Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
56 private GateID gateID = null;
57 private AMID amid = null;
58 private SubscriberID subscriberID = null;
59 private TransactionID transactionID = null;
60 private org.pcmm.gates.impl.GateSpec gateSpec = null;
61 private ITrafficProfile trafficProfile = null;
62 private final List<IClassifier> classifiers = Lists.newArrayListWithExpectedSize(4);
63 private PCMMError error = null;
65 public PCMMGateReq build() {
66 return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifiers, gateID, error);
69 public void setAmId(final AmId qosAmId) {
70 amid = new AMID(qosAmId.getAmType().shortValue(), qosAmId.getAmTag().shortValue());
73 public void setSubscriberId(final InetAddress qosSubId) {
74 subscriberID = new SubscriberID(qosSubId);
77 public void setGateSpec(final GateSpec qosGateSpec, final ServiceFlowDirection scnDirection) {
79 final ServiceFlowDirection qosDir;
80 if (scnDirection != null) {
81 qosDir = scnDirection;
83 if (qosGateSpec.getDirection() != null) {
84 qosDir = qosGateSpec.getDirection();
86 // TODO - determine if this is a valid default value
87 qosDir = ServiceFlowDirection.Ds;
91 final Direction gateDir;
92 if (qosDir == ServiceFlowDirection.Ds) {
93 gateDir = Direction.DOWNSTREAM;
95 gateDir = Direction.UPSTREAM;
100 final byte gateTosMask;
102 final TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite();
103 if (tosOverwrite != null) {
105 TosByte tosMask = qosGateSpec.getDscpTosMask();
106 if (tosMask != null) {
107 gateTosMask = tosMask.getValue().byteValue();
109 gateTosMask = (byte) 0xff;
112 // TODO - These values appear to be required
116 gateSpec = new org.pcmm.gates.impl.GateSpec(gateDir, dscptos, gateTosMask);
119 public void setTrafficProfile(final TrafficProfile qosTrafficProfile) {
120 if (qosTrafficProfile.getServiceClassName() != null) {
122 new DOCSISServiceClassNameTrafficProfile(qosTrafficProfile.getServiceClassName().getValue());
126 private InetAddress getByName(final String ipAddressStr) {
128 return InetAddress.getByName(ipAddressStr);
129 } catch (UnknownHostException e) {
130 logger.error(e.getMessage());
135 public void setClassifiers(final List<ClassifierContainer> classifiers) {
136 checkNotNull(classifiers);
138 for (ClassifierContainer container : classifiers) {
139 final ClassifierChoice choice = container.getClassifierChoice();
140 final Short index = container.getClassifierId();
142 if (choice instanceof QosClassifierChoice) {
143 addClassifier(((QosClassifierChoice) choice).getClassifier());
145 else if (choice instanceof ExtClassifierChoice) {
146 addExtClassifier(index, ((ExtClassifierChoice) choice).getExtClassifier());
148 else if (choice instanceof Ipv6ClassifierChoice) {
149 addIpv6Classifier(index, ((Ipv6ClassifierChoice) choice).getIpv6Classifier());
152 throw new IllegalStateException("Unknown ClassifierChoice: " + choice);
157 private void addClassifier(final Classifier qosClassifier) {
158 // TODO - try and make these variables immutable
159 Protocol protocol = null;
160 byte tosOverwrite = 0;
161 byte tosMask = (byte)0x0;
162 Inet4Address srcAddress = null;
163 Inet4Address dstAddress = null;
164 short srcPort = (short) 0;
165 short dstPort = (short) 0;
166 byte priority = (byte) 64;
169 if (qosClassifier.getProtocol() != null) {
170 protocol = Protocol.valueOf(qosClassifier.getProtocol().getValue().shortValue());
172 if (qosClassifier.getSrcIp() != null) {
173 final InetAddress sip = getByName(qosClassifier.getSrcIp().getValue());
174 if (sip != null && sip instanceof Inet4Address) {
175 srcAddress = (Inet4Address) sip;
178 if (qosClassifier.getDstIp() != null) {
179 final InetAddress dip = getByName(qosClassifier.getDstIp().getValue());
180 if (dip != null && dip instanceof Inet4Address) {
181 dstAddress = (Inet4Address) dip;
184 if (qosClassifier.getSrcPort() != null) {
185 srcPort = qosClassifier.getSrcPort().getValue().shortValue();
187 if (qosClassifier.getDstPort() != null) {
188 dstPort = qosClassifier.getDstPort().getValue().shortValue();
190 if (qosClassifier.getTosByte() != null) {
191 tosOverwrite = qosClassifier.getTosByte().getValue().byteValue();
192 if (qosClassifier.getTosMask() != null) {
193 tosMask = qosClassifier.getTosMask().getValue().byteValue();
195 // set default TOS mask
196 tosMask = (byte) 0xff;
199 // push the classifier to the gate request
200 classifiers.add(new org.pcmm.gates.impl.Classifier(protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort,
204 private void addExtClassifier(final Short index, final ExtClassifier qosExtClassifier) {
205 // Extended classifier
206 final byte priority = (byte) 64;
207 final ActivationState activationState = ActivationState.ACTIVE;
208 // Protocol -- zero is match any
209 final Protocol protocol;
210 if (qosExtClassifier.getProtocol() != null) {
211 protocol = Protocol.valueOf(qosExtClassifier.getProtocol().getValue().shortValue());
213 protocol = Protocol.NONE;
216 // default source port range must be set to match any even if qosExtClassifier has no range
217 // match any port range is 0-65535, NOT 0-0
218 // TODO - try to make these two variables immutable
219 short srcStartPort = (short) 0;
220 short srcEndPort = (short) 65535;
221 if (qosExtClassifier.getSrcPortStart() != null) {
222 srcStartPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
223 srcEndPort = srcStartPort;
224 if (qosExtClassifier.getSrcPortEnd() != null) {
225 srcEndPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
227 if (srcStartPort > srcEndPort) {
228 logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same",
229 srcStartPort, srcEndPort);
230 srcEndPort = srcStartPort;
233 // default destination port range must be set to match any even if qosExtClassifier has no range
234 // match any port range is 0-65535, NOT 0-0
235 // TODO - try to make these two variables immutable
236 short dstStartPort = (short) 0;
237 short dstEndPort = (short) 65535;
238 if (qosExtClassifier.getDstPortStart() != null) {
239 dstStartPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
240 dstEndPort = dstStartPort;
241 if (qosExtClassifier.getDstPortEnd() != null) {
242 dstEndPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
244 if (dstStartPort > dstEndPort) {
245 logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same",
246 dstStartPort, dstEndPort);
247 dstEndPort = dstStartPort;
252 // TODO - try to make these two variables immutable
253 byte tosOverwrite = 0;
254 byte tosMask = (byte)0x00;
255 if (qosExtClassifier.getTosByte() != null) {
256 // OR in the DSCP/TOS enable bit 0x01
257 tosOverwrite = (byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01);
258 if (qosExtClassifier.getTosMask() != null) {
259 tosMask = qosExtClassifier.getTosMask().getValue().byteValue();
261 // set default TOS mask
262 tosMask = (byte) 0xff;
266 // TODO - find out what the classifier ID should really be. It was never getting set previously
267 final short classifierId = (short)index;
269 // TODO - find out what the action value should really be. It was never getting set previously
270 final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
272 // push the extended classifier to the gate request
273 classifiers.add(new org.pcmm.gates.impl.ExtendedClassifier(protocol, tosOverwrite, tosMask,
274 getInet4Address(qosExtClassifier.getSrcIp()), getInet4Address(qosExtClassifier.getDstIp()),
275 srcStartPort, dstStartPort, priority, getInet4Address(qosExtClassifier.getSrcIpMask()),
276 getInet4Address(qosExtClassifier.getDstIpMask()), srcEndPort, dstEndPort, classifierId, activationState,
280 private Inet4Address getInet4Address(
281 final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address address) {
282 if (address != null) {
283 final InetAddress out = getByName(address.getValue());
284 if (out != null && out instanceof Inet4Address) {
285 return (Inet4Address) out;
291 private void addIpv6Classifier(final Short index, final Ipv6Classifier qosIpv6Classifier) {
294 if (qosIpv6Classifier.getNextHdr() != null) {
295 nextHdr = qosIpv6Classifier.getNextHdr().getValue().shortValue();
297 // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
299 nextHdr = (short) 256;
302 // Source IPv6 address & prefix len
303 // TODO - try to make these two variables immutable
304 byte srcPrefixLen = (byte) 128;
305 Inet6Address srcAddress = null;
306 if (qosIpv6Classifier.getSrcIp6() != null) {
307 String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
308 String Ipv6AddressStr = parts[0];
309 srcAddress = (Inet6Address) getByName(Ipv6AddressStr);
310 if (parts.length > 1) {
311 srcPrefixLen = (byte) Integer.parseInt(parts[1]);
313 srcPrefixLen = (byte) 128;
318 // TODO - try to make these two variables immutable
319 Inet6Address dstAddress = null;
320 byte dstPrefLen = (byte) 128;
321 // Destination IPv6 address & prefix len
322 if (qosIpv6Classifier.getDstIp6() != null) {
323 final String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
324 final String Ipv6AddressStr = parts[0];
325 dstAddress = (Inet6Address)getByName(Ipv6AddressStr);
326 if (parts.length > 1) dstPrefLen = (byte) Integer.parseInt(parts[1]);
327 else dstPrefLen = (byte) 128;
330 // default source port range must be set to match any -- even if qosExtClassifier has no range value
331 // match any port range is 0-65535, NOT 0-0
332 short srcPortBegin = (short) 0;
333 short srcPortEnd = (short) 65535;
334 if (qosIpv6Classifier.getSrcPortStart() != null) {
335 srcPortBegin = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
336 srcPortEnd = srcPortBegin;
337 if (qosIpv6Classifier.getSrcPortEnd() != null) {
338 srcPortEnd = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
340 if (srcPortBegin > srcPortEnd) {
341 logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same",
342 srcPortBegin, srcPortEnd);
343 srcPortEnd = srcPortBegin;
347 // default destination port range must be set to match any -- even if qosExtClassifier has no range value
348 // match any port range is 0-65535, NOT 0-0
349 short dstPortBegin = (short) 0;
350 short dstPortEnd = (short) 65535;
351 if (qosIpv6Classifier.getDstPortStart() != null) {
352 dstPortBegin = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
353 dstPortEnd = dstPortBegin;
354 if (qosIpv6Classifier.getDstPortEnd() != null) {
355 dstPortEnd = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
357 if (dstPortBegin > dstPortEnd) {
358 logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same",
359 dstPortBegin, dstPortEnd);
360 dstPortEnd = dstPortBegin;
365 if (qosIpv6Classifier.getTcLow() != null)
366 tcLow = qosIpv6Classifier.getTcLow().getValue().byteValue();
367 else tcLow = (byte) 0x00;
370 if (qosIpv6Classifier.getTcHigh() != null)
371 tcHigh = qosIpv6Classifier.getTcHigh().getValue().byteValue();
372 else tcHigh = (byte) 0x00;
375 if (qosIpv6Classifier.getTcHigh() != null)
376 tcMask = qosIpv6Classifier.getTcHigh().getValue().byteValue();
377 else if (qosIpv6Classifier.getTcLow() != null) tcMask = (byte) 0xff;
378 else tcMask = (byte) 0x00;
380 // TODO - find out what the classifier ID should really be. It was never getting set previously
381 final short classifierId = (short)index;
383 // TODO - find out what the action value should really be. It was never getting set previously
384 final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
386 // push the IPv6 classifier to the gate request
388 new org.pcmm.gates.impl.IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin, (byte) 64,
389 srcPortEnd, dstPortEnd, classifierId, ActivationState.ACTIVE, action, FlowLabel.VALID, tcLow,
390 tcHigh, tcMask, qosIpv6Classifier.getFlowLabel().intValue(), nextHdr, srcPrefixLen, dstPrefLen));