FreeCalypso > hg > fc-magnetite
comparison src/g23m-gprs/cl/clqos.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
182:f02d0a0e1849 | 183:219afcfc6250 |
---|---|
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 } |