Bump to odlparent 3.1.0 and yangtools 2.0.3
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / gates / impl / DOCSISFlowSpecTrafficProfile.java
1 /*
2  * Copyright (c) 2016 Applied Broadband, Inc. 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.pcmm.gates.impl;
10
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;
16
17 import java.util.Arrays;
18 import java.nio.ByteBuffer;
19
20 /**
21  * The DOCSIS Flow Spec object defines the Flow Spec Traffic Profile of a Gate.
22  *
23  */
24 public class DOCSISFlowSpecTrafficProfile extends PCMMBaseObject implements ITrafficProfile {
25
26     private final Logger logger = LoggerFactory.getLogger(DOCSISFlowSpecTrafficProfile.class);
27     public static final byte STYPE = 1;
28     public static final byte SERVICE_NUMBER = 2;
29
30     /**
31      * The envelope
32      */
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;
41     
42     /**
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]
51      */
52     public DOCSISFlowSpecTrafficProfile(final int tokenBucketRate,
53                                         final int tokenBucketSize,
54                                         final int peakDataRate,
55                                         final int minimumPolicedUnit,
56                                         final int maximumPacketSize,
57                                         final int rate,
58                                         final int slackTerm ) {
59         this(DEFAULT_ENVELOP, tokenBucketRate, tokenBucketSize, peakDataRate,
60              minimumPolicedUnit, maximumPacketSize, rate, slackTerm);
61     }
62
63     /**
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]
73      */
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,
80                                            final int rate,
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;
88         this.rate = rate;
89         this.slackTerm = slackTerm;
90         this.envelope = envelope;
91     }
92
93     @Override
94     public byte getEnvelop() {
95         return envelope;
96     }
97
98     /**
99      * Returns the token bucket rate value
100      * @return - the token bucket rate value
101      */
102     public int getTokenBucketRate() {
103         return tokenBucketRate;
104     }
105
106     /**
107      * Returns the token bucket size value
108      * @return - the token bucket size value
109      */
110     public int getTokenBucketSize() {
111         return tokenBucketSize;
112     }
113
114     /**
115      * Returns the peak data rate value
116      * @return - the peak data rate value
117      */
118     public int getPeakDataRate() {
119         return peakDataRate;
120     }
121
122     /**
123      * Returns the minimum policed unit value
124      * @return - the minimum policed unit value
125      */
126     public int getMinimumPolicedUnit() {
127         return minimumPolicedUnit;
128     }
129
130     /**
131      * Returns the maximum packet size value
132      * @return - the maximum packet size value
133      */
134     public int getMaximumPacketSize() {
135         return maximumPacketSize;
136     }
137
138     /**
139      * Returns the rate value
140      * @return - the rate value
141      */
142     public int getRate() {
143         return rate;
144     }
145
146     /**
147      * Returns the slack term value
148      * @return - the slack term value
149      */
150     public int getSlackTerm() {
151         return slackTerm;
152     }
153
154     @Override
155     protected byte[] getBytes() {
156         final byte[] data = new byte[4+(4*7*3)];
157         ByteBuffer buffer = ByteBuffer.wrap(data);
158         
159         //
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
163         //
164         final float fTokenBucketRate = tokenBucketRate;
165         final float fTokenBucketSize = tokenBucketSize;
166         final float fPeakDataRate = peakDataRate;
167         final float fRate = rate;
168
169         buffer.put(envelope);
170         buffer.put(SERVICE_NUMBER);
171         buffer.put((byte)0); // reserved
172         buffer.put((byte)0); // reserved
173         
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);
182         
183         // Reserved Envelope
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);
191         
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);
200         
201         if (buffer.hasRemaining()) {
202             logger.error("Original buffer too large");
203         }
204         
205         return data;
206     }
207
208     @Override
209     public boolean equals(final Object o) {
210         if (this == o) {
211             return true;
212         }
213         if (!(o instanceof DOCSISFlowSpecTrafficProfile)) {
214             return false;
215         }
216         if (!super.equals(o)) {
217             return false;
218         }
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);
228     }
229
230     @Override
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;
241         return result;
242     }
243
244     private static int byteToInt(final byte[] data, int start) {
245         return (int)(data[start]   << 24 |
246                      data[start+1] << 16 |
247                      data[start+2] << 8  |
248                      data[start+3]);
249     }
250
251     private static float byteToFloat(final byte[] data, int start) {
252         return (float)(data[start]   << 24 |
253                        data[start+1] << 16 |
254                        data[start+2] << 8  |
255                        data[start+3]);
256     }
257     
258     /**
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.
263      */
264     public static DOCSISFlowSpecTrafficProfile parse(final byte[] data) {
265         byte env = 0;
266         int mpu=0,mps=0,st=0;
267         float tbr=0,tbs=0,pdr=0,r=0;
268
269         env = data[0];
270
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);
278         //
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
282         //
283         int itbr = Math.round(tbr), itbs = Math.round(tbs),
284             ipdr = Math.round(pdr), ir = Math.round(r);
285         
286         return new DOCSISFlowSpecTrafficProfile(env, itbr, itbs, ipdr,
287                                                 mpu, mps, ir, st);
288     }
289
290   /**
291    * {@inheritDoc}
292    */
293   public String toString() {
294     final int sbSize = 1000;
295     final String variableSeparator = "\n";
296     final StringBuffer sb = new StringBuffer(sbSize);
297
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);
313
314     return sb.toString();
315   }
316 }