2 * Copyright (c) 2016 Applied Broadband, Inc. 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.pcmm.gates.impl;
11 import org.pcmm.base.impl.PCMMBaseObject;
12 import org.pcmm.gates.ITrafficProfile;
13 import org.pcmm.utils.PCMMUtils;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
17 import java.util.Arrays;
18 import java.nio.ByteBuffer;
21 * The DOCSIS Flow Spec object defines the Flow Spec Traffic Profile of a Gate.
24 public class DOCSISFlowSpecTrafficProfile extends PCMMBaseObject implements ITrafficProfile {
26 private final Logger logger = LoggerFactory.getLogger(DOCSISFlowSpecTrafficProfile.class);
27 public static final byte STYPE = 1;
28 public static final byte SERVICE_NUMBER = 2;
33 private final byte envelope;
34 private final int tokenBucketRate;
35 private final int tokenBucketSize;
36 private final int peakDataRate;
37 private final int minimumPolicedUnit;
38 private final int maximumPacketSize;
39 private final int rate;
40 private final int slackTerm;
43 * Constructor using the default envelope values
44 * @param tokenBucketRate - Token Bucket Rate value [r]
45 * @param tokenBucketSize - Token Bucket Size value [b]
46 * @param peakDataRate - Peak Data Rate value [p]
47 * @param minimumPolicedUnit - Minimum Policed Unit value [m]
48 * @param maximumPacketSize - Maximum Packet Size value [M]
49 * @param rate - Rate value [R]
50 * @param slackTerm - Slack Term value [S]
52 public DOCSISFlowSpecTrafficProfile(final int tokenBucketRate,
53 final int tokenBucketSize,
54 final int peakDataRate,
55 final int minimumPolicedUnit,
56 final int maximumPacketSize,
58 final int slackTerm ) {
59 this(DEFAULT_ENVELOP, tokenBucketRate, tokenBucketSize, peakDataRate,
60 minimumPolicedUnit, maximumPacketSize, rate, slackTerm);
64 * Constructor to set all values
65 * @param envelope - the envelope value
66 * @param tokenBucketRate - Token Bucket Rate value [r]
67 * @param tokenBucketSize - Token Bucket Size value [b]
68 * @param peakDataRate - Peak Data Rate value [p]
69 * @param minimumPolicedUnit - Minimum Policed Unit value [m]
70 * @param maximumPacketSize - Maximum Packet Size value [M]
71 * @param rate - Rate value [R]
72 * @param slackTerm - Slack Term value [S]
74 protected DOCSISFlowSpecTrafficProfile(final byte envelope,
75 final int tokenBucketRate,
76 final int tokenBucketSize,
77 final int peakDataRate,
78 final int minimumPolicedUnit,
79 final int maximumPacketSize,
81 final int slackTerm) {
82 super(SNum.TRAFFIC_PROFILE, STYPE);
83 this.tokenBucketRate = tokenBucketRate;
84 this.tokenBucketSize = tokenBucketSize;
85 this.peakDataRate = peakDataRate;
86 this.minimumPolicedUnit = minimumPolicedUnit;
87 this.maximumPacketSize = maximumPacketSize;
89 this.slackTerm = slackTerm;
90 this.envelope = envelope;
94 public byte getEnvelop() {
99 * Returns the token bucket rate value
100 * @return - the token bucket rate value
102 public int getTokenBucketRate() {
103 return tokenBucketRate;
107 * Returns the token bucket size value
108 * @return - the token bucket size value
110 public int getTokenBucketSize() {
111 return tokenBucketSize;
115 * Returns the peak data rate value
116 * @return - the peak data rate value
118 public int getPeakDataRate() {
123 * Returns the minimum policed unit value
124 * @return - the minimum policed unit value
126 public int getMinimumPolicedUnit() {
127 return minimumPolicedUnit;
131 * Returns the maximum packet size value
132 * @return - the maximum packet size value
134 public int getMaximumPacketSize() {
135 return maximumPacketSize;
139 * Returns the rate value
140 * @return - the rate value
142 public int getRate() {
147 * Returns the slack term value
148 * @return - the slack term value
150 public int getSlackTerm() {
155 protected byte[] getBytes() {
156 final byte[] data = new byte[4+(4*7*3)];
157 ByteBuffer buffer = ByteBuffer.wrap(data);
160 // Ok I know this looks crazy but PCMM Flow Spec encodes some values as floats
161 // even though they do not contain fractional values, so we 'integerize' them
162 // in the constructor and class internals
164 final float fTokenBucketRate = tokenBucketRate;
165 final float fTokenBucketSize = tokenBucketSize;
166 final float fPeakDataRate = peakDataRate;
167 final float fRate = rate;
169 buffer.put(envelope);
170 buffer.put(SERVICE_NUMBER);
171 buffer.put((byte)0); // reserved
172 buffer.put((byte)0); // reserved
174 // Authorized Envelope
175 buffer.putFloat(fTokenBucketRate);
176 buffer.putFloat(fTokenBucketSize);
177 buffer.putFloat(fPeakDataRate);
178 buffer.putInt(minimumPolicedUnit);
179 buffer.putInt(maximumPacketSize);
180 buffer.putFloat(fRate);
181 buffer.putInt(slackTerm);
184 buffer.putFloat(fTokenBucketRate);
185 buffer.putFloat(fTokenBucketSize);
186 buffer.putFloat(fPeakDataRate);
187 buffer.putInt(minimumPolicedUnit);
188 buffer.putInt(maximumPacketSize);
189 buffer.putFloat(fRate);
190 buffer.putInt(slackTerm);
192 // Committed Envelope
193 buffer.putFloat(fTokenBucketRate);
194 buffer.putFloat(fTokenBucketSize);
195 buffer.putFloat(fPeakDataRate);
196 buffer.putInt(minimumPolicedUnit);
197 buffer.putInt(maximumPacketSize);
198 buffer.putFloat(fRate);
199 buffer.putInt(slackTerm);
201 if (buffer.hasRemaining()) {
202 logger.error("Original buffer too large");
209 public boolean equals(final Object o) {
213 if (!(o instanceof DOCSISFlowSpecTrafficProfile)) {
216 if (!super.equals(o)) {
219 final DOCSISFlowSpecTrafficProfile that = (DOCSISFlowSpecTrafficProfile) o;
220 return (envelope == that.envelope) &&
221 (tokenBucketRate == that.tokenBucketRate) &&
222 (tokenBucketSize == that.tokenBucketSize) &&
223 (peakDataRate == that.peakDataRate) &&
224 (minimumPolicedUnit == that.minimumPolicedUnit) &&
225 (maximumPacketSize == that.maximumPacketSize) &&
226 (rate == that.rate) &&
227 (slackTerm == that.slackTerm);
231 public int hashCode() {
232 int result = super.hashCode();
233 result = 31 * result + tokenBucketRate;
234 result = 31 * result + tokenBucketSize;
235 result = 31 * result + peakDataRate;
236 result = 31 * result + minimumPolicedUnit;
237 result = 31 * result + maximumPacketSize;
238 result = 31 * result + rate;
239 result = 31 * result + slackTerm;
240 result = 31 * result + (int) envelope;
244 private static int byteToInt(final byte[] data, int start) {
245 return (int)(data[start] << 24 |
246 data[start+1] << 16 |
251 private static float byteToFloat(final byte[] data, int start) {
252 return (float)(data[start] << 24 |
253 data[start+1] << 16 |
259 * Returns a DOCSISFlowSpecTrafficProfile object from a byte array
260 * @param data - the data to parse
261 * @return - the object
262 * TODO - make me more robust as RuntimeExceptions can be thrown here.
264 public static DOCSISFlowSpecTrafficProfile parse(final byte[] data) {
266 int mpu=0,mps=0,st=0;
267 float tbr=0,tbs=0,pdr=0,r=0;
271 tbr = byteToFloat(data, 4);
272 tbs = byteToFloat(data, 8);
273 pdr = byteToFloat(data, 12);
274 mpu = byteToInt(data, 16);
275 mps = byteToInt(data, 20);
276 r = byteToFloat(data, 24);
277 st = byteToInt(data, 28);
279 // Ok I know this looks crazy but PCMM Flow Spec encodes some values as floats
280 // even though they do not contain fractional values, so we 'integerize' them
281 // in the constructor and class internals
283 int itbr = Math.round(tbr), itbs = Math.round(tbs),
284 ipdr = Math.round(pdr), ir = Math.round(r);
286 return new DOCSISFlowSpecTrafficProfile(env, itbr, itbs, ipdr,
293 public String toString() {
294 final int sbSize = 1000;
295 final String variableSeparator = "\n";
296 final StringBuffer sb = new StringBuffer(sbSize);
298 sb.append("Envelope: ").append(envelope);
299 sb.append(variableSeparator);
300 sb.append("TokenBucketRate: ").append(tokenBucketRate);
301 sb.append(variableSeparator);
302 sb.append("TokenBucketSize: ").append(tokenBucketSize);
303 sb.append(variableSeparator);
304 sb.append("PeakDataRate: ").append(peakDataRate);
305 sb.append(variableSeparator);
306 sb.append("MinimumPolicedUnit: ").append(minimumPolicedUnit);
307 sb.append(variableSeparator);
308 sb.append("MaximumPacketSize: ").append(maximumPacketSize);
309 sb.append(variableSeparator);
310 sb.append("Rate: ").append(rate);
311 sb.append(variableSeparator);
312 sb.append("SlackTerm: ").append(slackTerm);
314 return sb.toString();