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.GateState;
43 import org.pcmm.gates.impl.GateTimeInfo;
44 import org.pcmm.gates.impl.GateUsageInfo;
45 import org.pcmm.gates.impl.PCMMError;
46 import org.pcmm.gates.impl.PCMMGateReq;
47 import org.pcmm.gates.impl.SubscriberID;
48 import org.pcmm.gates.impl.TransactionID;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * Build PCMM gate requests from API QoS Gate objects
55 public class PCMMGateReqBuilder {
57 private final Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
59 private GateID gateID = null;
60 private AMID amid = null;
61 private SubscriberID subscriberID = null;
62 private TransactionID transactionID = null;
63 private org.pcmm.gates.impl.GateSpec gateSpec = null;
64 private ITrafficProfile trafficProfile = null;
65 private final List<IClassifier> classifiers = Lists.newArrayListWithExpectedSize(4);
66 private PCMMError error = null;
67 private GateState gateState = null;
68 private GateTimeInfo gateTimeInfo = null;
69 private GateUsageInfo gateUsageInfo = null;
71 public PCMMGateReq build() {
72 return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifiers,
73 gateID, error, gateState, gateTimeInfo, gateUsageInfo);
76 public void setAmId(final AmId qosAmId) {
77 amid = new AMID(qosAmId.getAmType().shortValue(), qosAmId.getAmTag().shortValue());
80 public void setSubscriberId(final InetAddress qosSubId) {
81 subscriberID = new SubscriberID(qosSubId);
84 public void setGateSpec(final GateSpec qosGateSpec, final ServiceFlowDirection scnDirection) {
86 final ServiceFlowDirection qosDir;
87 if (scnDirection != null) {
88 qosDir = scnDirection;
90 if (qosGateSpec.getDirection() != null) {
91 qosDir = qosGateSpec.getDirection();
93 // TODO - determine if this is a valid default value
94 qosDir = ServiceFlowDirection.Ds;
98 final Direction gateDir;
99 if (qosDir == ServiceFlowDirection.Ds) {
100 gateDir = Direction.DOWNSTREAM;
102 gateDir = Direction.UPSTREAM;
105 // DSCP/TOS Overwrite
107 final byte gateTosMask;
109 final TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite();
110 if (tosOverwrite != null) {
112 TosByte tosMask = qosGateSpec.getDscpTosMask();
113 if (tosMask != null) {
114 gateTosMask = tosMask.getValue().byteValue();
116 gateTosMask = (byte) 0xff;
119 // TODO - These values appear to be required
123 gateSpec = new org.pcmm.gates.impl.GateSpec(gateDir, dscptos, gateTosMask);
126 public void setTrafficProfile(final TrafficProfile qosTrafficProfile) {
127 if (qosTrafficProfile.getServiceClassName() != null) {
129 new DOCSISServiceClassNameTrafficProfile(qosTrafficProfile.getServiceClassName().getValue());
133 private InetAddress getByName(final String ipAddressStr) {
135 return InetAddress.getByName(ipAddressStr);
136 } catch (UnknownHostException e) {
137 logger.error(e.getMessage());
142 public void setClassifiers(final List<ClassifierContainer> classifiers) {
143 checkNotNull(classifiers);
145 for (ClassifierContainer container : classifiers) {
146 final ClassifierChoice choice = container.getClassifierChoice();
147 final Short index = container.getClassifierId();
149 if (choice instanceof QosClassifierChoice) {
150 addClassifier(index, ((QosClassifierChoice) choice).getClassifier());
152 else if (choice instanceof ExtClassifierChoice) {
153 addExtClassifier(index, ((ExtClassifierChoice) choice).getExtClassifier());
155 else if (choice instanceof Ipv6ClassifierChoice) {
156 addIpv6Classifier(index, ((Ipv6ClassifierChoice) choice).getIpv6Classifier());
159 throw new IllegalStateException("Unknown ClassifierChoice: " + choice);
164 private void addClassifier(final Short index,final Classifier qosClassifier) {
165 // TODO - try and make these variables immutable
166 Protocol protocol = null;
167 byte tosOverwrite = 0;
168 byte tosMask = (byte)0x0;
169 Inet4Address srcAddress = null;
170 Inet4Address dstAddress = null;
171 short srcPort = (short) 0;
172 short dstPort = (short) 0;
173 byte priority = (byte) 64;
174 //byte priority = index.byteValue();
178 if (qosClassifier.getProtocol() != null) {
179 protocol = Protocol.valueOf(qosClassifier.getProtocol().getValue().shortValue());
181 if (qosClassifier.getSrcIp() != null) {
182 final InetAddress sip = getByName(qosClassifier.getSrcIp().getValue());
183 if (sip != null && sip instanceof Inet4Address) {
184 srcAddress = (Inet4Address) sip;
187 if (qosClassifier.getDstIp() != null) {
188 final InetAddress dip = getByName(qosClassifier.getDstIp().getValue());
189 if (dip != null && dip instanceof Inet4Address) {
190 dstAddress = (Inet4Address) dip;
193 if (qosClassifier.getSrcPort() != null) {
194 srcPort = qosClassifier.getSrcPort().getValue().shortValue();
196 if (qosClassifier.getDstPort() != null) {
197 dstPort = qosClassifier.getDstPort().getValue().shortValue();
199 if (qosClassifier.getTosByte() != null) {
200 tosOverwrite = qosClassifier.getTosByte().getValue().byteValue();
201 if (qosClassifier.getTosMask() != null) {
202 tosMask = qosClassifier.getTosMask().getValue().byteValue();
204 // set default TOS mask
205 tosMask = (byte) 0xff;
208 // push the classifier to the gate request
209 classifiers.add(new org.pcmm.gates.impl.Classifier(protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort,
213 private void addExtClassifier(final Short index, final ExtClassifier qosExtClassifier) {
214 // Extended classifier
215 final byte priority = (byte) 64;
216 final ActivationState activationState = ActivationState.ACTIVE;
217 // Protocol -- zero is match any
218 final Protocol protocol;
219 if (qosExtClassifier.getProtocol() != null) {
220 protocol = Protocol.valueOf(qosExtClassifier.getProtocol().getValue().shortValue());
222 protocol = Protocol.NONE;
225 // default source port range must be set to match any even if qosExtClassifier has no range
226 // match any port range is 0-65535, NOT 0-0
227 // TODO - try to make these two variables immutable
228 short srcStartPort = (short) 0;
229 short srcEndPort = (short) 65535;
230 if (qosExtClassifier.getSrcPortStart() != null) {
231 srcStartPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
232 srcEndPort = srcStartPort;
233 if (qosExtClassifier.getSrcPortEnd() != null) {
234 srcEndPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
236 if (srcStartPort > srcEndPort) {
237 logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same",
238 srcStartPort, srcEndPort);
239 srcEndPort = srcStartPort;
242 // default destination port range must be set to match any even if qosExtClassifier has no range
243 // match any port range is 0-65535, NOT 0-0
244 // TODO - try to make these two variables immutable
245 short dstStartPort = (short) 0;
246 short dstEndPort = (short) 65535;
247 if (qosExtClassifier.getDstPortStart() != null) {
248 dstStartPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
249 dstEndPort = dstStartPort;
250 if (qosExtClassifier.getDstPortEnd() != null) {
251 dstEndPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
253 if (dstStartPort > dstEndPort) {
254 logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same",
255 dstStartPort, dstEndPort);
256 dstEndPort = dstStartPort;
261 // TODO - try to make these two variables immutable
262 byte tosOverwrite = 0;
263 byte tosMask = (byte)0x00;
264 if (qosExtClassifier.getTosByte() != null) {
265 // OR in the DSCP/TOS enable bit 0x01
266 tosOverwrite = (byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01);
267 if (qosExtClassifier.getTosMask() != null) {
268 tosMask = qosExtClassifier.getTosMask().getValue().byteValue();
270 // set default TOS mask
271 tosMask = (byte) 0xff;
275 // TODO - find out what the classifier ID should really be. It was never getting set previously
276 final short classifierId = (short)index;
278 // TODO - find out what the action value should really be. It was never getting set previously
279 final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
281 // push the extended classifier to the gate request
282 classifiers.add(new org.pcmm.gates.impl.ExtendedClassifier(protocol, tosOverwrite, tosMask,
283 getInet4Address(qosExtClassifier.getSrcIp()), getInet4Address(qosExtClassifier.getDstIp()),
284 srcStartPort, dstStartPort, priority, getInet4Address(qosExtClassifier.getSrcIpMask()),
285 getInet4Address(qosExtClassifier.getDstIpMask()), srcEndPort, dstEndPort, classifierId, activationState,
289 private Inet4Address getInet4Address(
290 final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address address) {
291 if (address != null) {
292 final InetAddress out = getByName(address.getValue());
293 if (out != null && out instanceof Inet4Address) {
294 return (Inet4Address) out;
300 private void addIpv6Classifier(final Short index, final Ipv6Classifier qosIpv6Classifier) {
303 if (qosIpv6Classifier.getNextHdr() != null) {
304 nextHdr = qosIpv6Classifier.getNextHdr().getValue().shortValue();
306 // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
308 nextHdr = (short) 256;
311 // Source IPv6 address & prefix len
312 // TODO - try to make these two variables immutable
313 byte srcPrefixLen = (byte) 128;
314 Inet6Address srcAddress = null;
315 if (qosIpv6Classifier.getSrcIp6() != null) {
316 String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
317 String Ipv6AddressStr = parts[0];
318 srcAddress = (Inet6Address) getByName(Ipv6AddressStr);
319 if (parts.length > 1) {
320 srcPrefixLen = (byte) Integer.parseInt(parts[1]);
322 srcPrefixLen = (byte) 128;
327 // TODO - try to make these two variables immutable
328 Inet6Address dstAddress = null;
329 byte dstPrefLen = (byte) 128;
330 // Destination IPv6 address & prefix len
331 if (qosIpv6Classifier.getDstIp6() != null) {
332 final String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
333 final String Ipv6AddressStr = parts[0];
334 dstAddress = (Inet6Address)getByName(Ipv6AddressStr);
335 if (parts.length > 1) dstPrefLen = (byte) Integer.parseInt(parts[1]);
336 else dstPrefLen = (byte) 128;
339 // default source port range must be set to match any -- even if qosExtClassifier has no range value
340 // match any port range is 0-65535, NOT 0-0
341 short srcPortBegin = (short) 0;
342 short srcPortEnd = (short) 65535;
343 if (qosIpv6Classifier.getSrcPortStart() != null) {
344 srcPortBegin = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
345 srcPortEnd = srcPortBegin;
346 if (qosIpv6Classifier.getSrcPortEnd() != null) {
347 srcPortEnd = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
349 if (srcPortBegin > srcPortEnd) {
350 logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same",
351 srcPortBegin, srcPortEnd);
352 srcPortEnd = srcPortBegin;
356 // default destination port range must be set to match any -- even if qosExtClassifier has no range value
357 // match any port range is 0-65535, NOT 0-0
358 short dstPortBegin = (short) 0;
359 short dstPortEnd = (short) 65535;
360 if (qosIpv6Classifier.getDstPortStart() != null) {
361 dstPortBegin = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
362 dstPortEnd = dstPortBegin;
363 if (qosIpv6Classifier.getDstPortEnd() != null) {
364 dstPortEnd = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
366 if (dstPortBegin > dstPortEnd) {
367 logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same",
368 dstPortBegin, dstPortEnd);
369 dstPortEnd = dstPortBegin;
374 if (qosIpv6Classifier.getTcLow() != null)
375 tcLow = qosIpv6Classifier.getTcLow().getValue().byteValue();
376 else tcLow = (byte) 0x00;
379 if (qosIpv6Classifier.getTcHigh() != null)
380 tcHigh = qosIpv6Classifier.getTcHigh().getValue().byteValue();
381 else tcHigh = (byte) 0x00;
384 if (qosIpv6Classifier.getTcHigh() != null)
385 tcMask = qosIpv6Classifier.getTcHigh().getValue().byteValue();
386 else if (qosIpv6Classifier.getTcLow() != null) tcMask = (byte) 0xff;
387 else tcMask = (byte) 0x00;
389 // TODO - find out what the classifier ID should really be. It was never getting set previously
390 final short classifierId = (short)index;
392 // TODO - find out what the action value should really be. It was never getting set previously
393 final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
395 // push the IPv6 classifier to the gate request
397 new org.pcmm.gates.impl.IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin, (byte) 64,
398 srcPortEnd, dstPortEnd, classifierId, ActivationState.ACTIVE, action, FlowLabel.VALID, tcLow,
399 tcHigh, tcMask, qosIpv6Classifier.getFlowLabel().intValue(), nextHdr, srcPrefixLen, dstPrefLen));