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)];
158 float fTokenBucketRate = tokenBucketRate;
159 float fTokenBucketSize = tokenBucketSize;
160 float fPeakDataRate = peakDataRate;
164 // Ok I know this looks crazy but PCMM Flow Spec encodes some values as floats
165 // even though they do not contain fractional values, so we 'integerize' them
166 // in the constructor and class internals
168 Arrays.fill(data, (byte) 0);
170 data[1] = SERVICE_NUMBER;
171 data[2] = 0; // reserved
172 data[3] = 0; // reserved
174 // Authorized Envelope
175 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketRate).array(), 0, data, 4, 4);
176 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketSize).array(), 0, data, 8, 4);
177 System.arraycopy(ByteBuffer.allocate(4).putFloat(fPeakDataRate).array(), 0, data, 12, 4);
178 System.arraycopy(ByteBuffer.allocate(4).putInt(minimumPolicedUnit).array(), 0, data, 16, 4);
179 System.arraycopy(ByteBuffer.allocate(4).putInt(maximumPacketSize).array(), 0, data, 20, 4);
180 System.arraycopy(ByteBuffer.allocate(4).putFloat(fRate).array(), 0, data, 24, 4);
181 System.arraycopy(ByteBuffer.allocate(4).putInt(slackTerm).array(), 0, data, 28, 4);
184 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketRate).array(), 0, data, 32, 4);
185 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketSize).array(), 0, data, 36, 4);
186 System.arraycopy(ByteBuffer.allocate(4).putFloat(fPeakDataRate).array(), 0, data, 40, 4);
187 System.arraycopy(ByteBuffer.allocate(4).putInt(minimumPolicedUnit).array(), 0, data, 44, 4);
188 System.arraycopy(ByteBuffer.allocate(4).putInt(maximumPacketSize).array(), 0, data, 48, 4);
189 System.arraycopy(ByteBuffer.allocate(4).putFloat(fRate).array(), 0, data, 52, 4);
190 System.arraycopy(ByteBuffer.allocate(4).putInt(slackTerm).array(), 0, data, 56, 4);
192 // Committed Envelope
193 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketRate).array(), 0, data, 60, 4);
194 System.arraycopy(ByteBuffer.allocate(4).putFloat(fTokenBucketSize).array(), 0, data, 64, 4);
195 System.arraycopy(ByteBuffer.allocate(4).putFloat(fPeakDataRate).array(), 0, data, 68, 4);
196 System.arraycopy(ByteBuffer.allocate(4).putInt(minimumPolicedUnit).array(), 0, data, 72, 4);
197 System.arraycopy(ByteBuffer.allocate(4).putInt(maximumPacketSize).array(), 0, data, 76, 4);
198 System.arraycopy(ByteBuffer.allocate(4).putFloat(fRate).array(), 0, data, 80, 4);
199 System.arraycopy(ByteBuffer.allocate(4).putInt(slackTerm).array(), 0, data, 84, 4);
204 public boolean equals(final Object o) {
208 if (!(o instanceof DOCSISFlowSpecTrafficProfile)) {
211 if (!super.equals(o)) {
214 final DOCSISFlowSpecTrafficProfile that = (DOCSISFlowSpecTrafficProfile) o;
215 return (envelope == that.envelope) &&
216 (tokenBucketRate == that.tokenBucketRate) &&
217 (tokenBucketSize == that.tokenBucketSize) &&
218 (peakDataRate == that.peakDataRate) &&
219 (minimumPolicedUnit == that.minimumPolicedUnit) &&
220 (maximumPacketSize == that.maximumPacketSize) &&
221 (rate == that.rate) &&
222 (slackTerm == that.slackTerm);
226 public int hashCode() {
227 int result = super.hashCode();
228 result = 31 * result + tokenBucketRate;
229 result = 31 * result + tokenBucketSize;
230 result = 31 * result + peakDataRate;
231 result = 31 * result + minimumPolicedUnit;
232 result = 31 * result + maximumPacketSize;
233 result = 31 * result + rate;
234 result = 31 * result + slackTerm;
235 result = 31 * result + (int) envelope;
239 private static int byteToInt(final byte[] data, int start) {
240 return (int)(data[start] << 24 |
241 data[start+1] << 16 |
246 private static float byteToFloat(final byte[] data, int start) {
247 return (float)(data[start] << 24 |
248 data[start+1] << 16 |
254 * Returns a DOCSISFlowSpecTrafficProfile object from a byte array
255 * @param data - the data to parse
256 * @return - the object
257 * TODO - make me more robust as RuntimeExceptions can be thrown here.
259 public static DOCSISFlowSpecTrafficProfile parse(final byte[] data) {
261 int mpu=0,mps=0,st=0;
262 float tbr=0,tbs=0,pdr=0,r=0;
266 tbr = byteToFloat(data, 4);
267 tbs = byteToFloat(data, 8);
268 pdr = byteToFloat(data, 12);
269 mpu = byteToInt(data, 16);
270 mps = byteToInt(data, 20);
271 r = byteToFloat(data, 24);
272 st = byteToInt(data, 28);
274 // Ok I know this looks crazy but PCMM Flow Spec encodes some values as floats
275 // even though they do not contain fractional values, so we 'integerize' them
276 // in the constructor and class internals
278 int itbr = Math.round(tbr), itbs = Math.round(tbs),
279 ipdr = Math.round(pdr), ir = Math.round(r);
281 return new DOCSISFlowSpecTrafficProfile(env, itbr, itbs, ipdr,
288 public String toString() {
289 final int sbSize = 1000;
290 final String variableSeparator = "\n";
291 final StringBuffer sb = new StringBuffer(sbSize);
293 sb.append("Envelope: ").append(envelope);
294 sb.append(variableSeparator);
295 sb.append("TokenBucketRate: ").append(tokenBucketRate);
296 sb.append(variableSeparator);
297 sb.append("TokenBucketSize: ").append(tokenBucketSize);
298 sb.append(variableSeparator);
299 sb.append("PeakDataRate: ").append(peakDataRate);
300 sb.append(variableSeparator);
301 sb.append("MinimumPolicedUnit: ").append(minimumPolicedUnit);
302 sb.append(variableSeparator);
303 sb.append("MaximumPacketSize: ").append(maximumPacketSize);
304 sb.append(variableSeparator);
305 sb.append("Rate: ").append(rate);
306 sb.append(variableSeparator);
307 sb.append("SlackTerm: ").append(slackTerm);
309 return sb.toString();