comparison src/g23m-gprs/cl/clqos.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
comparison
equal deleted inserted replaced
0:b6a5e36de839 1:d393cd9bb723
1 /*-----------------------------------------------------------------------------
2 | Project : 3G UMTS PS
3 | Module : CL
4 +------------------------------------------------------------------------------
5 | Copyright 2003 Texas Instruments.
6 | All rights reserved.
7 |
8 | This file is confidential and a trade secret of Texas
9 | Instruments .
10 | The receipt of or possession of this file does not convey
11 | any rights to reproduce or disclose its contents or to
12 | manufacture, use, or sell anything it may describe, in
13 | whole, or in part, without the specific written consent of
14 | Texas Instruments.
15 +------------------------------------------------------------------------------
16 | Purpose: QoS handling functions.
17 | For design details, see:
18 | 8010.149 CL SAP
19 +----------------------------------------------------------------------------*/
20
21 #ifndef CLQOS_C
22 #define CLQOS_C
23 #endif
24
25 #ifndef ENTITY_CL
26 #define ENTITY_CL
27 #endif
28 #define ENTITY_CLT
29
30 /*==== INCLUDES =============================================================*/
31
32 #include "typedefs.h" /* to get TI data types */
33 #include "vsi.h" /* to get a lot of macros */
34 #include "gsm.h" /* to get a lot of macros */
35 #include "message.h" /* to get the message definitions for sm */
36 #include "prim.h" /* to get the definitions of used SAP and directions */
37 #include "p_cl.val" /* to get the type of sgsn_rel*/
38 #include "p_8010_152_ps_include.h" /*to get T_PS_qos_rXX*/
39 #include "cl_inline.h"
40
41
42 typedef U8 T_CL_result; /*I really don't like this ! Can we do something in cl.sap ?*/
43
44 /*==== CONST ================================================================*/
45
46 /*
47 * Conversion table for 1/n in T_ratio.
48 * Contains 1/n * 1E9 entries used for scaling.
49 */
50 static const U32 cl_qos_ratio_table[10] = {
51 0UL,
52 1000000000UL, /* 1E9 / 1 */
53 500000000UL, /* 1E9 / 2 */
54 333333333UL, /* 1E9 / 3 */
55 250000000UL, /* 1E9 / 4 */
56 200000000UL, /* 1E9 / 5 */
57 166666667UL, /* 1E9 / 6 */
58 142857143UL, /* 1E9 / 7 */
59 125000000UL, /* 1E9 / 8 */
60 111111111UL /* 1E9 / 9 */
61 };
62
63 /*==== LOCAL VARS ===========================================================*/
64
65 /*==== PRIVATE FUNCTIONS ====================================================*/
66
67 /*-----------------------------------------------------------------------------
68 | Function : cl_qos_ratio_to_U32
69 +------------------------------------------------------------------------------
70 | Description : Conversion function: T_ratio to integer
71 |
72 | Parameters : T_ratio
73 |
74 | Return : ratio as integer
75 +----------------------------------------------------------------------------*/
76 static U32 cl_qos_ratio_to_U32(U8 ratio_mant, U8 ratio_exp)
77 {
78 U32 value;
79 int count;
80
81 /* Error checks */
82 if (ratio_exp > (U8)9)
83 {
84 /*TRACE_ERROR( "QoS ratio exponent parameter out of bounds!" );*/
85 return 0;
86 }
87 else
88 {
89 if (ratio_mant > (U8)9)
90 {
91 /*TRACE_ERROR( "QoS ratio exponent parameter out of bounds!" );*/
92 return 0;
93 }
94 else
95 {
96 if (ratio_exp == (U8)9 && ratio_mant < (U8)5)
97 {
98 /*TRACE_ERROR( "QoS ratio parameter exceeds data type range!" );*/
99 return 0;
100 }
101 }
102 }
103
104 for (count = 9-(int)ratio_exp, value = 1UL; count > 0; count--)
105 {
106 value *= 10;
107 }
108 /* Get real value by rounding 1/x and dividing by 10^(9-ratio_exp) */
109 value = (cl_qos_ratio_table[(U16)ratio_mant] + (value >> 1)) / value;
110
111 return value;
112 }
113
114 /*-----------------------------------------------------------------------------
115 | Function : cl_qos_r99_to_delay
116 +------------------------------------------------------------------------------
117 | Description : Given an input R99 QoS, return the corresponding R97 delay
118 | parameter
119 |
120 | Parameters : R99 Qos
121 |
122 | Return : Delay
123 +----------------------------------------------------------------------------*/
124 static T_PS_delay cl_qos_r99_to_delay(T_PS_qos_r99 *src_qos_r99)
125 {
126 T_PS_delay delay;
127
128 /* Traffic class / handling priority */
129 switch ((T_PS_tc)src_qos_r99->tc)
130 {
131 case PS_TC_SUB: /* 0 - Subscribed */
132 delay = PS_DELAY_SUB;
133 break;
134 case PS_TC_CONV: /* 1 - Conversational */
135 delay = PS_DELAY_1;
136 break;
137 case PS_TC_STREAM: /* 2 - Streaming */
138 delay = PS_DELAY_1;
139 break;
140 case PS_TC_INTER: /* 3 - Interactive */
141 switch (src_qos_r99->handling_pri)
142 {
143 case PS_HANDLING_PRI_1:
144 delay = PS_DELAY_1;
145 break;
146 case PS_HANDLING_PRI_2:
147 delay = PS_DELAY_2;
148 break;
149 case PS_HANDLING_PRI_3:
150 default: /* For safety */
151 delay = PS_DELAY_3;
152 break;
153 } /* switch */
154 break;
155 case PS_TC_BG: /* 4 - Background */
156 delay = PS_DELAY_4;
157 break;
158 default: /* 5, 6, 7 or other garbage */
159 delay = PS_DELAY_SUB;
160 break;
161 } /* switch */
162
163 return delay;
164 } /* cl_qos_r99_to_delay */
165
166 /*-----------------------------------------------------------------------------
167 | Function : cl_qos_r99_to_relclass
168 +------------------------------------------------------------------------------
169 | Description : Given an input R99 QoS, return the corresponding R97 relclass
170 | parameter
171 |
172 | Parameters : R99 Qos
173 |
174 | Return : Reliability class
175 +----------------------------------------------------------------------------*/
176 static T_PS_relclass cl_qos_r99_to_relclass(T_PS_qos_r99 *src_qos_r99)
177 {
178 U32 sdu_err;
179 T_PS_relclass relclass;
180
181 /* First, convert SDU error ratio to integral number */
182 sdu_err = cl_qos_ratio_to_U32(src_qos_r99->sdu_err_ratio.ratio_mant,
183 src_qos_r99->sdu_err_ratio.ratio_exp);
184
185 if (sdu_err == 0UL)
186 { /* SDU err ratio == subscribed value */
187 relclass = PS_RELCLASS_SUB; /* 0 */
188 }
189 else
190 {
191 if (sdu_err >= 100000UL)
192 { /* SDU err ratio <= 1E-5 */
193 relclass = PS_LLC_RLC_PROT; /* 2 */
194 }
195 else
196 {
197 if (sdu_err >= 2000UL)
198 { /* 1E-5 < SDU err ratio <= 5E-4 */
199 relclass = PS_RLC_PROT; /* 3 */
200 }
201 else
202 { /* SDU err ratio > 5E-4 */
203 if (src_qos_r99->ber.ratio_exp > (U8)4 ||
204 (src_qos_r99->ber.ratio_exp == (U8)4 && src_qos_r99->ber.ratio_mant >= (U8)2))
205 {
206 /* BER <= 2E-4 */
207 relclass = PS_PROT; /* 4 */
208 }
209 else
210 { /* BER > 2E-4 */
211 relclass = PS_NO_REL; /* 5 */
212 }
213 }
214 }
215 } /* if (sdu_err ...) */
216
217 return relclass;
218 }
219
220 /*==== PUBLIC FUNCTIONS =====================================================*/
221
222 /*-----------------------------------------------------------------------------
223 | Function : cl_qos_convert_r99_to_r97_req
224 +------------------------------------------------------------------------------
225 | Description : Function for converting a R99 QoS parameter set to a R97/R98
226 | ditto. Conversion rules according to [3G 23.107, sec 9]
227 |
228 | Parameters : Originating R99 QoS parameter struct
229 | Destination R97 QoS parameter struct (overwritten in this function)
230 |
231 | Return : Conversion result and Destination R97 QoS parameter struct.
232 +----------------------------------------------------------------------------*/
233 T_CL_result cl_qos_convert_r99_to_r97(T_PS_qos_r99 *src_qos_r99,
234 T_PS_qos_r97 *dst_qos_r97)
235 {
236 T_CL_result success = (T_CL_result)TRUE;
237 U16 count, max_rate;
238
239 dst_qos_r97->delay = (U8)cl_qos_r99_to_delay(src_qos_r99);
240
241 /*
242 * SDU error ratio / Residual bit error ratio
243 */
244 dst_qos_r97->relclass = (U8)cl_qos_r99_to_relclass(src_qos_r99);
245
246 /*
247 * Maximum bit-rate
248 *
249 * In case max uplink and downlink data rates differ, [3G 23.107]
250 * says to map according to max(R99_uplink, R99_downlink),
251 * i.e. the higher of the two.
252 */
253 max_rate = (src_qos_r99->max_rate_ul > src_qos_r99->max_rate_dl ?
254 src_qos_r99->max_rate_ul : src_qos_r99->max_rate_dl);
255
256 if (max_rate == (U16)PS_MAX_BR_UL_SUB)
257 { /* Subscribed */
258 dst_qos_r97->peak = (U8)PS_PEAK_SUB;
259 }
260 else
261 { /* ! Subscribed */
262 /* Perform pseudo log2(bit-rate). Really, we are finding the highest set
263 * bit to use in our comparison rather than making a *huge*
264 * if-[else if]*-else clause.
265 * Fixed ceiling to 2048 (count < 12) => max_rate <= 2^11 */
266 for (count = (U16)4; ((max_rate >> count) != 0) && count < (U16)12; count++);
267
268 /* The quick / code optimal way:
269 * dst_qos_r97->peak = count - 3; */
270
271 switch (count)
272 {
273 case 4: dst_qos_r97->peak = (U8)PS_PEAK_1K; break;
274 case 5: dst_qos_r97->peak = (U8)PS_PEAK_2K; break;
275 case 6: dst_qos_r97->peak = (U8)PS_PEAK_4K; break;
276 case 7: dst_qos_r97->peak = (U8)PS_PEAK_8K; break;
277 case 8: dst_qos_r97->peak = (U8)PS_PEAK_16K; break;
278 case 9: dst_qos_r97->peak = (U8)PS_PEAK_32K; break;
279 case 10: dst_qos_r97->peak = (U8)PS_PEAK_64K; break;
280 case 11: dst_qos_r97->peak = (U8)PS_PEAK_128K; break;
281 case 12: dst_qos_r97->peak = (U8)PS_PEAK_256K; break;
282 } /* switch */
283 } /* if - Subscribed */
284
285 /* R97 peak throughput class is fixed to 31 (best effort) */
286 dst_qos_r97->mean = (U8)PS_MEAN_BEST;
287 dst_qos_r97->preced = (U8)PS_PRECED_SUB;
288
289 return success;
290 }
291
292 /*-----------------------------------------------------------------------------
293 | Function : cl_qos_convert_r97_to_r99_req
294 +------------------------------------------------------------------------------
295 | Description : Function for converting a R97/R98 QoS parameter set to a R99
296 | ditto. Conversion rules according to [3G 23.107, sec 9]
297 |
298 | Parameters : Originating R97 QoS parameter struct
299 | Destination R99 QoS parameter struct (overwritten in this function)
300 |
301 | Return : Conversion result and Destination R99 QoS parameter struct.
302 +----------------------------------------------------------------------------*/
303 T_CL_result cl_qos_convert_r97_to_r99(T_PS_qos_r97 *src_qos_r97,
304 T_PS_qos_r99 *dst_qos_r99)
305 {
306 T_CL_result success = (T_CL_result)TRUE;
307
308 /* Delay parameter */
309 switch ((T_PS_delay)src_qos_r97->delay)
310 {
311 case PS_DELAY_SUB: /* 0 */
312 dst_qos_r99->tc = (U8)PS_TC_SUB;
313 dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_SUB;
314 break;
315 case PS_DELAY_1: /* 1 */
316 dst_qos_r99->tc = (U8)PS_TC_INTER;
317 dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_1;
318 break;
319 case PS_DELAY_2: /* 2 */
320 dst_qos_r99->tc = (U8)PS_TC_INTER;
321 dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_2;
322 break;
323 case PS_DELAY_3: /* 3 */
324 dst_qos_r99->tc = (U8)PS_TC_INTER;
325 dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_3;
326 break;
327 case PS_DELAY_4: /* 4 */
328 dst_qos_r99->tc = (U8)PS_TC_BG;
329 dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_SUB;
330 break;
331 default: /* 5 - 7 or other garbage */
332 /* Error handling? */
333 success = (T_CL_result)FALSE;
334 break;
335 } /* switch */
336
337 /* Reliability class */
338 switch ((T_PS_relclass)src_qos_r97->relclass)
339 {
340 case PS_RELCLASS_SUB: /* 0 - Subscribed */
341 dst_qos_r99->sdu_err_ratio.ratio_mant = dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)0;
342 dst_qos_r99->ber.ratio_mant = dst_qos_r99->ber.ratio_exp = (U8)0;
343 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_SUB;
344 break;
345 case PS_GTP_LLC_RLC_PROT: /* 1 - Acknowledged GTP, LLC, and RLC */
346 dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1;
347 dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)6; /* SDU error ratio = 1E-6 */
348 dst_qos_r99->ber.ratio_mant = (U8)1;
349 dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */
350 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO;
351 break;
352 case PS_LLC_RLC_PROT: /* 2 - Unacknowledged GTP; Acknowledged LLC and RLC */
353 dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1;
354 dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)6; /* SDU error ratio = 1E-6 */
355 dst_qos_r99->ber.ratio_mant = (U8)1;
356 dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */
357 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO;
358 break;
359 case PS_RLC_PROT: /* 3 - Unacknowledged GTP and LLC; Acknowledged RLC */
360 dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1;
361 dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)4; /* SDU error ratio = 1E-4 */
362 dst_qos_r99->ber.ratio_mant = (U8)1;
363 dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */
364 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO;
365 break;
366 case PS_PROT: /* 4 - Unacknowledged GTP, LLC, and RLC */
367 dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1;
368 dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)3; /* SDU error ratio = 1E-3 */
369 dst_qos_r99->ber.ratio_mant = (U8)1;
370 dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */
371 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO;
372 break;
373 case PS_NO_REL: /* 5 - Unacknowledged GTP, LLC, and RLC (Unprotected) */
374 dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1;
375 dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)3; /* SDU error ratio = 1E-3 */
376 dst_qos_r99->ber.ratio_mant = (U8)4;
377 dst_qos_r99->ber.ratio_exp = (U8)3; /* Residual BER = 4E-3 */
378 dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_YES;
379 break;
380 default: /* 6, 7 or other garbage */
381 /* Error handling? */
382 success = (T_CL_result)FALSE;
383 break;
384 } /* switch */
385
386 /* Peak throughput parameter */
387 /* NOTE: Could be optimized heavily into the following:
388 * dst_qos_r99->max_br_dl = dst_qos_r99->max_br_ul = (peak == 0 ? 0 : 4 << peak)
389 */
390
391 switch ((T_PS_peak)src_qos_r97->peak)
392 {
393 case PS_PEAK_SUB: /* 0 */
394 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)PS_MAX_BR_UL_SUB;
395 break;
396 case PS_PEAK_1K: /* 1 */
397 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)8;
398 break;
399 case PS_PEAK_2K: /* 2 */
400 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)16;
401 break;
402 case PS_PEAK_4K: /* 3 */
403 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)32;
404 break;
405 case PS_PEAK_8K: /* 4 */
406 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)64;
407 break;
408 case PS_PEAK_16K: /* 5 */
409 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)128;
410 break;
411 case PS_PEAK_32K: /* 6 */
412 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)256;
413 break;
414 case PS_PEAK_64K: /* 7 */
415 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)512;
416 break;
417 case PS_PEAK_128K: /* 8 */
418 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)1024;
419 break;
420 case PS_PEAK_256K: /* 9 */
421 dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)2048;
422 break;
423 default:
424 /* Handling? */
425 success = (T_CL_result)FALSE;
426 break;
427 } /* switch */
428
429 /* R99 max SDU size is fixed to 1500 */
430 dst_qos_r99->max_sdu = (U16)1500;
431
432 /* Remaining R99 fields are not specified. We fill them in with subscribed */
433 dst_qos_r99->order = (U8)PS_ORDER_SUB;
434 dst_qos_r99->xfer_delay = (U16)PS_XFER_DELAY_SUB;
435 dst_qos_r99->guar_br_ul = (U16)PS_GUAR_BR_UL_SUB;
436 dst_qos_r99->guar_br_dl = (U16)PS_GUAR_BR_DL_SUB;
437
438 return success;
439 }
440
441 /*-----------------------------------------------------------------------------
442 | Function : cl_qos_use_ack_mode_llc_req
443 +------------------------------------------------------------------------------
444 | Description : Query function: Given input QoS, should NSAPI use acknowledged
445 | LLC mode?
446 |
447 | Parameters : Originating R99 QoS parameter struct
448 |
449 | Return : LLC mode
450 +----------------------------------------------------------------------------*/
451 T_PS_llc_mode cl_qos_use_ack_mode_llc(T_PS_qos_r99 *src_qos_r99)
452 {
453 T_PS_relclass relclass;
454 T_PS_llc_mode ret_val = PS_LLC_UNACKNOWLEDGED;
455
456 relclass = cl_qos_r99_to_relclass(src_qos_r99);
457
458 if (relclass == PS_GTP_LLC_RLC_PROT || relclass == PS_LLC_RLC_PROT)
459 {
460 ret_val = PS_LLC_ACKNOWLEDGED;
461 }
462
463 return ret_val;
464 }