Added support for RTP and UGS gate traffic profiles
[packetcable.git] / packetcable-policy-server / src / main / java / org / opendaylight / controller / packetcable / provider / PCMMGateReqBuilder.java
1 /*
2  * Copyright (c) 2015 CableLabs and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.packetcable.provider;
10
11 import static com.google.common.base.Preconditions.checkNotNull;
12
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.rev170125.ServiceFlowDirection;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.TosByte;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.ccap.attributes.AmId;
22 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.classifier.attributes.classifiers.ClassifierContainer;
23 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.classifier.attributes.classifiers.classifier.container.ClassifierChoice;
24 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.classifier.attributes.classifiers.classifier.container.classifier.choice.ExtClassifierChoice;
25 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.classifier.attributes.classifiers.classifier.container.classifier.choice.Ipv6ClassifierChoice;
26 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.classifier.attributes.classifiers.classifier.container.classifier.choice.QosClassifierChoice;
27 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.classifier.Classifier;
28 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.ext.classifier.ExtClassifier;
29 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.gate.spec.GateSpec;
30 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.ipv6.classifier.Ipv6Classifier;
31 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.TrafficProfile;
32 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.serviceclass.name.profile.ServiceClassNameProfile;
33 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.flow.spec.profile.FlowSpecProfile;
34 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.ugs.profile.UgsProfile;
35 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.rtp.profile.RtpProfile;
36 import org.pcmm.gates.IClassifier;
37 import org.pcmm.gates.IClassifier.Protocol;
38 import org.pcmm.gates.IExtendedClassifier;
39 import org.pcmm.gates.IExtendedClassifier.ActivationState;
40 import org.pcmm.gates.IGateSpec.Direction;
41 import org.pcmm.gates.IIPv6Classifier.FlowLabel;
42 import org.pcmm.gates.ITrafficProfile;
43 import org.pcmm.gates.impl.AMID;
44 import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
45 import org.pcmm.gates.impl.DOCSISFlowSpecTrafficProfile;
46 import org.pcmm.gates.impl.DOCSISUGSTrafficProfile;
47 import org.pcmm.gates.impl.DOCSISRTPTrafficProfile;
48 import org.pcmm.gates.impl.GateID;
49 import org.pcmm.gates.impl.GateState;
50 import org.pcmm.gates.impl.GateTimeInfo;
51 import org.pcmm.gates.impl.GateUsageInfo;
52 import org.pcmm.gates.impl.PCMMError;
53 import org.pcmm.gates.impl.PCMMGateReq;
54 import org.pcmm.gates.impl.SessionClassID;
55 import org.pcmm.gates.impl.SubscriberID;
56 import org.pcmm.gates.impl.TransactionID;
57 import org.pcmm.utils.PCMMUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.TrafficProfile;
61 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.traffic.profile.TrafficProfileChoice;
62 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.FlowSpecChoice;
63 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.ServiceClassNameChoice;
64 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.RtpChoice;
65 import org.opendaylight.yang.gen.v1.urn.packetcable.rev170125.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.UgsChoice;
66  
67 /**
68  * Build PCMM gate requests from API QoS Gate objects
69  */
70 public class PCMMGateReqBuilder {
71
72     private final Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
73
74     private GateID gateID = null;
75     private AMID amid = null;
76     private SubscriberID subscriberID = null;
77     private TransactionID transactionID = null;
78     private org.pcmm.gates.impl.GateSpec gateSpec = null;
79     private ITrafficProfile trafficProfile = null;
80     private final List<IClassifier> classifiers = Lists.newArrayListWithExpectedSize(4);
81     private PCMMError error = null;
82     private GateState gateState = null;
83     private GateTimeInfo gateTimeInfo = null;
84     private GateUsageInfo gateUsageInfo = null;
85
86     public PCMMGateReq build() {
87         return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifiers,
88                 gateID, error, gateState, gateTimeInfo, gateUsageInfo);
89     }
90
91     public void setAmId(final AmId qosAmId) {
92         amid = new AMID(qosAmId.getAmType().shortValue(), qosAmId.getAmTag().shortValue());
93     }
94
95     public void setSubscriberId(final InetAddress qosSubId) {
96         subscriberID = new SubscriberID(qosSubId);
97     }
98
99     public void setGateId(int gateId) {
100         gateID = new GateID(gateId);
101     }
102     
103     public void setGateSpec(final GateSpec qosGateSpec) {
104
105         final ServiceFlowDirection qosDir = qosGateSpec.getDirection();
106
107         // convert to PCMM API Type
108         final Direction gateDir;
109         if (qosDir == ServiceFlowDirection.Ds) {
110             gateDir = Direction.DOWNSTREAM;
111         } else {
112             gateDir = Direction.UPSTREAM;
113         }
114
115         final byte dscptos = 1;
116         final byte gateTosMask;
117
118         TosByte tosMask = qosGateSpec.getDscpTosMask();
119         if (tosMask != null) {
120             gateTosMask = tosMask.getValue().byteValue();
121         } else {
122             gateTosMask = (byte) 0xff;
123         }
124         
125         java.lang.Short scid = qosGateSpec.getSessionClassId();
126         byte bscid = 0;
127         if (scid != null) {
128             bscid = (byte)(qosGateSpec.getSessionClassId() & 0x00ff);
129         }
130         
131         java.lang.Long inactivity = qosGateSpec.getInactivityTimer();
132         short sinactivity = 300;
133         if (inactivity != null) {
134             sinactivity = inactivity.shortValue();
135         }
136         
137         gateSpec = new org.pcmm.gates.impl.GateSpec(gateDir, dscptos, gateTosMask,
138                                                     new SessionClassID(bscid),
139                                                     (short)1,(short)300,sinactivity,(short)0);
140    }
141
142     public void setTrafficProfile(final TrafficProfile qosTrafficProfile) {
143         TrafficProfileChoice choice = qosTrafficProfile.getTrafficProfileChoice();
144
145         if (choice instanceof ServiceClassNameChoice) {
146             ServiceClassNameProfile scnp = ((ServiceClassNameChoice)choice).getServiceClassNameProfile();
147             trafficProfile = new DOCSISServiceClassNameTrafficProfile(scnp.getServiceClassName().getValue());
148         }
149         else if (choice instanceof FlowSpecChoice) {
150             FlowSpecProfile fsp = ((FlowSpecChoice)choice).getFlowSpecProfile();
151             trafficProfile = new DOCSISFlowSpecTrafficProfile(fsp.getTokenBucketRate(),
152                                                               fsp.getTokenBucketSize(),
153                                                               fsp.getPeakDataRate(),
154                                                               fsp.getMinimumPolicedUnit(),
155                                                               fsp.getMaximumPacketSize(),
156                                                               fsp.getRate(),
157                                                               fsp.getSlackTerm());     
158         }
159         else if (choice instanceof UgsChoice) {
160             UgsProfile ugsp = ((UgsChoice)choice).getUgsProfile();
161             trafficProfile = new DOCSISUGSTrafficProfile(ugsp.getRequestTransmissionPolicy(),
162                                                          ugsp.getUnsolicitedGrantSize(),
163                                                          ugsp.getGrantsPerInterval(),
164                                                          ugsp.getNominalGrantInterval(),
165                                                          ugsp.getToleratedGrantJitter(),
166                                                          ugsp.getUpstreamPeakTrafficRate(),
167                                                          ugsp.getRequiredAttributeMask(),
168                                                          ugsp.getForbiddenAttributeMask(),
169                                                          ugsp.getAttributeAggregationRuleMask());     
170         }
171         else if (choice instanceof RtpChoice) {
172             RtpProfile rtpp = ((RtpChoice)choice).getRtpProfile();
173             trafficProfile = new DOCSISRTPTrafficProfile(rtpp.getRequestTransmissionPolicy(),
174                                                          rtpp.getMaximumSustainedTrafficRate(),
175                                                          rtpp.getMaximumTrafficBurst(),
176                                                          rtpp.getMinimumReservedTrafficRate(),
177                                                          rtpp.getAmrtrPacketSize().longValue(),
178                                                          rtpp.getMaximumConcatenatedBurst().longValue(),
179                                                          rtpp.getNominalPollingInterval(),
180                                                          rtpp.getToleratedPollJitter(),
181                                                          rtpp.getUpstreamPeakTrafficRate(),
182                                                          rtpp.getRequiredAttributeMask(),
183                                                          rtpp.getForbiddenAttributeMask(),
184                                                          rtpp.getAttributeAggregationRuleMask());     
185         }
186         else {
187             logger.debug("PCMMGateReq().setTrafficProfile() Unsupported Traffic Profile: " + choice.getClass().getName());
188         }
189     }
190
191     private InetAddress getByName(final String ipAddressStr) {
192         try {
193             return InetAddress.getByName(ipAddressStr);
194         } catch (UnknownHostException e) {
195             logger.error(e.getMessage());
196         }
197         return null;
198     }
199
200     public void setClassifiers(final List<ClassifierContainer> classifiers) {
201         checkNotNull(classifiers);
202
203         for (ClassifierContainer container : classifiers) {
204             final ClassifierChoice choice = container.getClassifierChoice();
205             final Short index = container.getClassifierId();
206
207             if (choice instanceof QosClassifierChoice) {
208                 addClassifier(index, ((QosClassifierChoice) choice).getClassifier());
209             }
210             else if (choice instanceof ExtClassifierChoice) {
211                 addExtClassifier(index, ((ExtClassifierChoice) choice).getExtClassifier());
212             }
213             else if (choice instanceof Ipv6ClassifierChoice) {
214                 addIpv6Classifier(index, ((Ipv6ClassifierChoice) choice).getIpv6Classifier());
215             }
216             else {
217                 throw new IllegalStateException("Unknown ClassifierChoice: " + choice);
218             }
219         }
220     }
221
222     private void addClassifier(final Short index,final Classifier qosClassifier) {
223         // TODO - try and make these variables immutable
224         Protocol protocol = null;
225         byte tosOverwrite = 0;
226         byte tosMask = (byte)0x0;
227         short srcPort = (short) 0;
228         short dstPort = (short) 0;
229
230         // Legacy classifier
231
232         // Protocol -- zero is match any
233         if (qosClassifier.getProtocol() != null) {
234             protocol = Protocol.valueOf(qosClassifier.getProtocol().getValue().shortValue());
235         } else {
236             protocol = Protocol.NONE;
237         }
238
239         // IP Addresss and mask wildcards - addr byte 0 for no match (or match anything)
240
241         Inet4Address srcAddress = (Inet4Address) getByName("0.0.0.0");
242
243         if (qosClassifier.getSrcIp() != null) {
244             srcAddress = (Inet4Address) getByName(qosClassifier.getSrcIp().getValue());
245         }
246
247         Inet4Address dstAddress = (Inet4Address) getByName("0.0.0.0");
248
249         if (qosClassifier.getDstIp() != null) {
250             dstAddress = (Inet4Address) getByName(qosClassifier.getDstIp().getValue());
251         }
252
253
254         if (qosClassifier.getSrcPort() != null) {
255             srcPort = qosClassifier.getSrcPort().getValue().shortValue();
256         }
257         if (qosClassifier.getDstPort() != null) {
258             dstPort = qosClassifier.getDstPort().getValue().shortValue();
259         }
260         if (qosClassifier.getTosByte() != null) {
261             tosOverwrite = qosClassifier.getTosByte().getValue().byteValue();
262             if (qosClassifier.getTosMask() != null) {
263                 tosMask = qosClassifier.getTosMask().getValue().byteValue();
264             } else {
265                 // set default TOS mask
266                 tosMask = (byte) 0xff;
267             }
268         }
269         //
270         // The packetcable.yang models priority as an uint8 which means the java generated
271         // implementation saves the value in a short, so we mask it back into a byte
272         //
273         byte priority = 64;
274         if (qosClassifier.getPriority() != null) {
275             short result = qosClassifier.getPriority();
276             priority = (byte)(result % 255);
277         }
278
279         // push the classifier to the gate request
280         classifiers.add(new org.pcmm.gates.impl.Classifier(protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort,
281                 dstPort, priority));
282     }
283
284     private void addExtClassifier(final Short index, final ExtClassifier qosExtClassifier) {
285         // Extended classifier
286         // Protocol -- zero is match any
287         final Protocol protocol;
288         if (qosExtClassifier.getProtocol() != null) {
289             protocol = Protocol.valueOf(qosExtClassifier.getProtocol().getValue().shortValue());
290         } else {
291             protocol = Protocol.NONE;
292         }
293
294         // default source port range must be set to match any even if qosExtClassifier has no range
295         // match any port range is 0-65535, NOT 0-0
296         // TODO - try to make these two variables immutable
297         short srcStartPort = (short) 0;
298         short srcEndPort = (short) 65535;
299         if (qosExtClassifier.getSrcPortStart() != null) {
300             srcStartPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
301             srcEndPort = srcStartPort;
302             if (qosExtClassifier.getSrcPortEnd() != null) {
303                 srcEndPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
304             }
305             if ((int)(srcStartPort & 0xffff) > (int) (srcEndPort & 0xffff)) {
306                 logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same",
307                         srcStartPort, srcEndPort);
308                 srcEndPort = srcStartPort;
309             }
310         }
311         // default destination port range must be set to match any even if qosExtClassifier has no range
312         // match any port range is 0-65535, NOT 0-0
313         // TODO - try to make these two variables immutable
314         short dstStartPort = (short) 0;
315         short dstEndPort = (short) 65535;
316         if (qosExtClassifier.getDstPortStart() != null) {
317             dstStartPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
318             dstEndPort = dstStartPort;
319             if (qosExtClassifier.getDstPortEnd() != null) {
320                 dstEndPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
321             }
322             if ((int)(dstStartPort & 0xffff) > (int)(dstEndPort & 0xffff)) {
323                 logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same",
324                         dstStartPort, dstEndPort);
325                 dstEndPort = dstStartPort;
326             }
327         }
328
329         // DSCP/TOP byte
330         // TODO - try to make these two variables immutable
331         byte tosOverwrite = 0;
332         byte tosMask = (byte)0x00;
333         if (qosExtClassifier.getTosByte() != null) {
334             // OR in the DSCP/TOS enable bit 0x01
335             tosOverwrite = (byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01);
336             if (qosExtClassifier.getTosMask() != null) {
337                 tosMask = qosExtClassifier.getTosMask().getValue().byteValue();
338             } else {
339                 // set default TOS mask
340                 tosMask = (byte) 0xff;
341             }
342         }
343
344         // IP Addresss and mask wildcards - addr byte 0 for no match (or match anything) and mask is 255.255.255.255 by default
345         Inet4Address srcIpAddr = (Inet4Address) getByName("0.0.0.0");
346
347         if (qosExtClassifier.getSrcIp() != null) {
348             srcIpAddr = getInet4Address(qosExtClassifier.getSrcIp());
349         }
350
351         Inet4Address dstIpAddr = (Inet4Address) getByName("0.0.0.0");
352         if (qosExtClassifier.getDstIp() != null) {
353             dstIpAddr = getInet4Address(qosExtClassifier.getDstIp());
354         }
355
356         //mask
357         Inet4Address srcIpMask = (Inet4Address) getByName("255.255.255.255");
358         if (qosExtClassifier.getSrcIpMask() != null) {
359             srcIpMask = getInet4Address(qosExtClassifier.getSrcIpMask());
360         }
361
362         Inet4Address dstIpMask = (Inet4Address) getByName("255.255.255.255");
363         if (qosExtClassifier.getDstIpMask() != null) {
364             dstIpMask = getInet4Address(qosExtClassifier.getDstIpMask());
365         }
366
367         // TODO - find out what the classifier ID should really be. It was never getting set previously
368         final short classifierId = (short)index;
369
370         // TODO - find out what the action value should really be. It was never getting set previously
371         final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
372
373         //
374         // Convert from Enum to byte for serialization
375         //
376         ActivationState activationState = ActivationState.ACTIVE;
377         if (qosExtClassifier.getActivationState() != null) {
378             activationState = ActivationState.valueOf((byte)qosExtClassifier.getActivationState().getIntValue());
379         }
380
381         //
382         // The packetcable.yang models priority as an uint8 which means the java generated
383         // implementation saves the value in a short, so we mask it back into a byte
384         //
385         byte priority = 64;
386         if (qosExtClassifier.getPriority() != null) {
387             short result = qosExtClassifier.getPriority();
388             priority = (byte)(result % 255);
389         }
390
391         // push the extended classifier to the gate request
392         classifiers.add(new org.pcmm.gates.impl.ExtendedClassifier(protocol, tosOverwrite, tosMask,
393                 srcIpAddr, dstIpAddr,
394                 srcStartPort, dstStartPort, priority, srcIpMask, dstIpMask, srcEndPort, dstEndPort, classifierId, activationState,
395                 action));
396     }
397
398     private Inet4Address getInet4Address(
399             final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address address) {
400         if (address != null) {
401             final InetAddress out = getByName(address.getValue());
402             if (out != null && out instanceof Inet4Address) {
403                 return (Inet4Address) out;
404             }
405         }
406         return null;
407     }
408
409     private void addIpv6Classifier(final Short index, final Ipv6Classifier qosIpv6Classifier) {
410         // Next Header
411         final short nextHdr;
412         if (qosIpv6Classifier.getNextHdr() != null) {
413             nextHdr = qosIpv6Classifier.getNextHdr().getValue().shortValue();
414         }
415         // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
416         else {
417             nextHdr = (short) 256;
418         }
419
420         // Source IPv6 address & prefix len
421         // TODO - try to make these two variables immutable
422         byte srcPrefixLen = (byte) 128;
423         Inet6Address srcAddress = (Inet6Address) getByName("0::0");
424
425         if (qosIpv6Classifier.getSrcIp6() != null) {
426             String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
427             String Ipv6AddressStr = parts[0];
428             srcAddress = (Inet6Address) getByName(Ipv6AddressStr);
429             if (parts.length > 1) {
430                 srcPrefixLen = (byte) Integer.parseInt(parts[1]);
431             } else {
432                 srcPrefixLen = (byte) 128;
433             }
434
435         }
436
437         // TODO - try to make these two variables immutable
438         Inet6Address dstAddress = (Inet6Address) getByName("0::0");
439
440         byte dstPrefLen = (byte) 128;
441         // Destination IPv6 address & prefix len
442         if (qosIpv6Classifier.getDstIp6() != null) {
443             final String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
444             final String Ipv6AddressStr = parts[0];
445             dstAddress = (Inet6Address)getByName(Ipv6AddressStr);
446             if (parts.length > 1) dstPrefLen = (byte) Integer.parseInt(parts[1]);
447             else dstPrefLen = (byte) 128;
448         }
449
450         // default source port range must be set to match any -- even if qosExtClassifier has no range value
451         // match any port range is 0-65535, NOT 0-0
452         short srcPortBegin = (short) 0;
453         short srcPortEnd = (short) 65535;
454         if (qosIpv6Classifier.getSrcPortStart() != null) {
455             srcPortBegin = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
456             srcPortEnd = srcPortBegin;
457             if (qosIpv6Classifier.getSrcPortEnd() != null) {
458                 srcPortEnd = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
459             }
460             if ((int)(srcPortBegin & 0xffff) > (int)(srcPortEnd & 0xffff)) {
461                 logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same",
462                         srcPortBegin, srcPortEnd);
463                 srcPortEnd = srcPortBegin;
464             }
465         }
466
467         // default destination port range must be set to match any -- even if qosExtClassifier has no range value
468         // match any port range is 0-65535, NOT 0-0
469         short dstPortBegin = (short) 0;
470         short dstPortEnd = (short) 65535;
471         if (qosIpv6Classifier.getDstPortStart() != null) {
472             dstPortBegin = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
473             dstPortEnd = dstPortBegin;
474             if (qosIpv6Classifier.getDstPortEnd() != null) {
475                 dstPortEnd = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
476             }
477             if ( (int)(dstPortBegin & 0xffff) > (int)(dstPortEnd & 0xffff)) {
478                 logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same",
479                         dstPortBegin, dstPortEnd);
480                 dstPortEnd = dstPortBegin;
481             }
482         }
483
484         final byte tcLow;
485         if (qosIpv6Classifier.getTcLow() != null)
486             tcLow = qosIpv6Classifier.getTcLow().getValue().byteValue();
487         else tcLow = (byte) 0x00;
488
489         final byte tcHigh;
490         if (qosIpv6Classifier.getTcHigh() != null)
491             tcHigh = qosIpv6Classifier.getTcHigh().getValue().byteValue();
492         else tcHigh = (byte) 0x00;
493
494         final byte tcMask;
495         if (qosIpv6Classifier.getTcHigh() != null)
496             tcMask = qosIpv6Classifier.getTcHigh().getValue().byteValue();
497         else if (qosIpv6Classifier.getTcLow() != null) tcMask = (byte) 0xff;
498         else tcMask = (byte) 0x00;
499
500         FlowLabel flowLabelFlag = FlowLabel.IRRELEVANT;
501         int flowLabelId = 0;
502
503         if (qosIpv6Classifier.getFlowLabel() != null) {
504             flowLabelFlag = FlowLabel.VALID;
505             flowLabelId = qosIpv6Classifier.getFlowLabel().intValue();
506         }
507
508
509         // TODO - find out what the classifier ID should really be. It was never getting set previously
510         final short classifierId = (short)index;
511
512         // TODO - find out what the action value should really be. It was never getting set previously
513         final IExtendedClassifier.Action action = IExtendedClassifier.Action.ADD;
514
515         //
516         // Convert from Enum to byte for serialization
517         //
518         ActivationState activationState = ActivationState.ACTIVE;
519         if (qosIpv6Classifier.getActivationState() != null) {
520             activationState = ActivationState.valueOf((byte)qosIpv6Classifier.getActivationState().getIntValue());
521         }
522
523         //
524         // The packetcable.yang models priority as an uint8 which means the java generated
525         // implementation saves the value in a short, so we mask it back into a byte
526         //
527         byte priority = 64;
528         if (qosIpv6Classifier.getPriority() != null) {
529             short result = qosIpv6Classifier.getPriority();
530             priority = (byte)(result % 255);
531         }
532
533         // push the IPv6 classifier to the gate request
534         classifiers.add(
535                 new org.pcmm.gates.impl.IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin, priority,
536                         srcPortEnd, dstPortEnd, classifierId, activationState, action, flowLabelFlag, tcLow,
537                         tcHigh, tcMask, flowLabelId, nextHdr, srcPrefixLen, dstPrefLen));
538     }
539 }