FreeCalypso > hg > fc-tourmaline
comparison src/g23m-gprs/sm/sm_qos.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:4e78acac3d88 | 1:fa8dc04885d8 |
---|---|
1 /*---------------------------------------------------------------------------- | |
2 | Project : 3G PS | |
3 | Module : SM | |
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: 3G QoS utility functions implementation in the SM entity. | |
17 | For design details, see: | |
18 | 8010.908 SM Detailed Specification | |
19 +---------------------------------------------------------------------------*/ | |
20 | |
21 /*==== DECLARATION CONTROL =================================================*/ | |
22 | |
23 /*==== INCLUDES =============================================================*/ | |
24 | |
25 #include "sm.h" | |
26 | |
27 #include "sm_qos.h" | |
28 | |
29 /*==== CONST ================================================================*/ | |
30 | |
31 struct qos_from_to { | |
32 U32 integer; | |
33 struct { | |
34 U16 ratio_mant, ratio_exp; | |
35 } ratio; | |
36 U8 packed; | |
37 }; | |
38 | |
39 /*@checked@*/ | |
40 static const struct qos_from_to sm_qos_ber_table[] = { | |
41 { 20UL, {(U16)5,(U16)2}, (U8)M_SM_QOS_BER_5E_2}, | |
42 { 100UL, {(U16)5,(U16)2}, (U8)M_SM_QOS_BER_1E_2}, | |
43 { 200UL, {(U16)5,(U16)3}, (U8)M_SM_QOS_BER_5E_3}, | |
44 { 250UL, {(U16)4,(U16)3}, (U8)M_SM_QOS_BER_4E_3}, | |
45 { 1000UL, {(U16)1,(U16)3}, (U8)M_SM_QOS_BER_1E_3}, | |
46 { 10000UL, {(U16)1,(U16)4}, (U8)M_SM_QOS_BER_1E_4}, | |
47 { 100000UL, {(U16)1,(U16)5}, (U8)M_SM_QOS_BER_1E_5}, | |
48 { 1000000UL, {(U16)1,(U16)6}, (U8)M_SM_QOS_BER_1E_6}, | |
49 {16666667UL, {(U16)6,(U16)8}, (U8)M_SM_QOS_BER_6E_8}, | |
50 { 0UL, {(U16)0,(U16)0}, (U8)M_SM_QOS_BER_SUB} | |
51 }; | |
52 | |
53 /*@checked@*/ | |
54 static const struct qos_from_to sm_qos_sdu_err_ratio_table[] = { | |
55 { 10UL, {(U16)1,(U16)1}, (U8)M_SM_QOS_SDU_ERR_1E_1}, /* NOTE: M_SM_QOS_SDU_ERR_1E_1 == 7 */ | |
56 { 100UL, {(U16)1,(U16)2}, (U8)M_SM_QOS_SDU_ERR_1E_2}, | |
57 { 143UL, {(U16)7,(U16)3}, (U8)M_SM_QOS_SDU_ERR_7E_3}, | |
58 { 1000UL, {(U16)1,(U16)3}, (U8)M_SM_QOS_SDU_ERR_1E_3}, | |
59 { 10000UL, {(U16)1,(U16)4}, (U8)M_SM_QOS_SDU_ERR_1E_4}, | |
60 { 100000UL, {(U16)1,(U16)5}, (U8)M_SM_QOS_SDU_ERR_1E_5}, | |
61 { 1000000UL, {(U16)1,(U16)6}, (U8)M_SM_QOS_SDU_ERR_1E_6}, | |
62 { 0UL, {(U16)0,(U16)0}, (U8)M_SM_QOS_SDU_ERR_SUB} | |
63 }; | |
64 | |
65 /* | |
66 * Conversion table for 1/n in T_ratio. | |
67 * Contains 1/n * 1E9 entries used for scaling. | |
68 */ | |
69 /*@checked@*/ | |
70 static const U32 sm_qos_ratio_table[10] = { | |
71 0UL, | |
72 1000000000UL, /* 1E9 / 1 */ | |
73 500000000UL, /* 1E9 / 2 */ | |
74 333333333UL, /* 1E9 / 3 */ | |
75 250000000UL, /* 1E9 / 4 */ | |
76 200000000UL, /* 1E9 / 5 */ | |
77 166666667UL, /* 1E9 / 6 */ | |
78 142857143UL, /* 1E9 / 7 */ | |
79 125000000UL, /* 1E9 / 8 */ | |
80 111111111UL /* 1E9 / 9 */ | |
81 }; | |
82 | |
83 /*==== LOCAL VARS ===========================================================*/ | |
84 | |
85 /*==== PRIVATE FUNCTIONS ====================================================*/ | |
86 | |
87 /* Conversion function: ratio to integer */ | |
88 static U32 sm_qos_ratio_to_U32(U8 ratio_mant, U8 ratio_exp) | |
89 /*@globals sm_qos_ratio_table@*/ | |
90 { | |
91 U32 value; | |
92 int count; | |
93 | |
94 /* Error checks */ | |
95 if (ratio_exp > (U8)9) | |
96 { | |
97 (void)TRACE_ERROR( "QoS ratio exponent parameter out of bounds!" ); | |
98 return 0; | |
99 } else if (ratio_mant > (U8)9) { | |
100 (void)TRACE_ERROR( "QoS ratio mantissa parameter out of bounds!" ); | |
101 return 0; | |
102 } else if (ratio_exp == (U8)9 && ratio_mant < (U8)5) { | |
103 (void)TRACE_ERROR( "QoS ratio parameter exceeds data type range!" ); | |
104 return 0; | |
105 } else { | |
106 for (count = 9-(int)ratio_exp, value = 1UL; count > 0; count--) { | |
107 value *= 10; | |
108 } | |
109 /* Get real value by rounding 1/x and dividing by 10^(9-ratio_exp) */ | |
110 value = (sm_qos_ratio_table[(U16)ratio_mant] + (value >> 1)) / value; | |
111 | |
112 return value; | |
113 } | |
114 } | |
115 | |
116 static U8 sm_qos_ratio_to_r99aim(const struct qos_from_to *table, | |
117 U8 ratio_mant, U8 ratio_exp) | |
118 /*@globals sm_qos_ratio_table@*/ | |
119 { | |
120 int index; | |
121 U32 value; | |
122 | |
123 /* Check for zero / subscribed parameter */ | |
124 if (ratio_mant == (U8)0) | |
125 { | |
126 return (U8)M_SM_QOS_BER_SUB; | |
127 } | |
128 | |
129 value = sm_qos_ratio_to_U32(ratio_mant, ratio_exp); | |
130 | |
131 /* Find the smallest matching table entry that is >= value */ | |
132 for (index = 0; | |
133 table[index].integer != 0 && table[index].integer < value; | |
134 index++) | |
135 {}; | |
136 | |
137 return (table[index].packed); | |
138 } | |
139 | |
140 static void sm_qos_r99aim_to_ratio(const struct qos_from_to *table, | |
141 U8 packed_ratio, | |
142 /*@out@*/U8 *ratio_mant, | |
143 /*@out@*/U8 *ratio_exp) | |
144 /*@modifies *ratio_mant, *ratio_exp@*/ | |
145 { | |
146 int index; | |
147 | |
148 for (index = 0; | |
149 table[index].integer != 0 && packed_ratio != table[index].packed; | |
150 index++) | |
151 {}; | |
152 | |
153 *ratio_mant = (U8)table[index].ratio.ratio_mant; | |
154 *ratio_exp = (U8)table[index].ratio.ratio_exp; | |
155 } | |
156 | |
157 static U32 sm_qos_r99aim_ratio_to_U32(const struct qos_from_to *table, | |
158 U8 packed_ratio) | |
159 { | |
160 int index; | |
161 | |
162 for (index = 0; | |
163 table[index].integer != 0 && packed_ratio != table[index].packed; | |
164 index++) | |
165 {}; | |
166 | |
167 return (table[index].integer); | |
168 } | |
169 | |
170 /* Helper function for converting "human readable" bit-rate values into | |
171 * packed 3G air interface equvalents. | |
172 * | |
173 * Parameters: Integer representation of the bit-rate | |
174 * Returns: Packed bit-rate value | |
175 * | |
176 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
177 */ | |
178 | |
179 static U8 sm_qos_bitrate_to_r99aim(U16 bitrate) /*@*/ | |
180 { | |
181 U8 result = (U8)0; | |
182 | |
183 if (bitrate < (U16)64) { | |
184 /* 1 - 63 kbps map to values 1 - 63 @ 1kbps increments*/ | |
185 result = (U8)bitrate; | |
186 } else if (bitrate < (U16)576) { | |
187 /* 64 - 568 kbps map to values 64 - 127 @ 8kbps increments. | |
188 * Values not on boundaries are rounded up. | |
189 * Formula: result = ((bitrate + 7) / 8) + (64 - (64 / 8)) */ | |
190 result = (U8)((U16)(bitrate + ((64 * 8) - 64 + 7)) >> 3); | |
191 } else if (bitrate < (U16)8640) { | |
192 /* 576 - 8640 kbps map to values 128 - 254 @ 64kbps increments. | |
193 * Values not on boundaries are rounded up. | |
194 * Formula: result = ((bitrate + 63) / 64) + (128 - (576 / 64)) */ | |
195 result = (U8)((U16)(bitrate + ((128 * 64) - 576 + 63)) >> 6); | |
196 } else { | |
197 /* Error */ | |
198 (void)TRACE_EVENT( "Warning: Bitrate parameter out of bounds! Truncated..." ); | |
199 result = (U8)254; | |
200 } | |
201 return result; | |
202 } | |
203 | |
204 /* Helper function for converting packed 3G air interface bit-rate values | |
205 * into "human readable" equvalents. | |
206 * | |
207 * Parameters: Packed bit-rate value | |
208 * Returns: Integer representation of the bit-rate | |
209 * | |
210 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
211 */ | |
212 | |
213 static U16 sm_qos_r99aim_to_bitrate(U8 packed_bitrate) /*@*/ | |
214 { | |
215 U16 bitrate = 0; | |
216 | |
217 if (packed_bitrate < (U8)64) { | |
218 bitrate = (U16)packed_bitrate; | |
219 } else if (packed_bitrate < (U8)128) { | |
220 bitrate = (U16)((packed_bitrate - (U8)56) << 3); | |
221 } else if (packed_bitrate < (U8)255) { | |
222 bitrate = (U16)((packed_bitrate - (U8)119) << 6); | |
223 } else { | |
224 bitrate = 0; | |
225 } | |
226 return bitrate; | |
227 } | |
228 | |
229 /* Helper function for converting "human readable" max SDU size values into | |
230 * packed 3G air interface equvalents. | |
231 * | |
232 * Parameters: Integer representation of the SDU size | |
233 * Returns: Packed SDU size value | |
234 * | |
235 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
236 */ | |
237 | |
238 static U8 sm_qos_max_sdu_to_r99aim(U16 sdu_size) /*@*/ | |
239 { | |
240 U8 result = (U8)0; | |
241 | |
242 if (sdu_size == (U16)PS_MAX_SDU_SUB) { | |
243 result = (U8)PS_MAX_SDU_SUB; | |
244 } else if (sdu_size <= (U16)1500) {/* Round up to nearest multiple of 10 and divide by 10. */ | |
245 result = (U8)((sdu_size + 9) / 10); | |
246 } else if (sdu_size <= (U16)1502) {/* Round 1501-1502 to 1502. */ | |
247 result = (U8)PS_MAX_SDU_1502; | |
248 } else if (sdu_size <= (U16)1510) {/* Round 1503-1510 to 1510. */ | |
249 result = (U8)PS_MAX_SDU_1510; | |
250 } else if (sdu_size <= (U16)1520) {/* Round 1511-1520 to 1520. */ | |
251 result = (U8)PS_MAX_SDU_1520; | |
252 } else { /* > 1520: We are forgiving and just truncate to 1520 */ | |
253 result = (U8)PS_MAX_SDU_1520; | |
254 (void)TRACE_EVENT( "Warning: Max SDU size specified > 1520! Truncated..." ); | |
255 } | |
256 return result; | |
257 } | |
258 | |
259 /* | |
260 * Helper function for converting packed 3G air interface max SDU size values | |
261 * into "human readable" equvalents. | |
262 * | |
263 * Parameters: Packed max SDU value | |
264 * Returns: Integer representation of the SDU size | |
265 * | |
266 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
267 */ | |
268 | |
269 static U16 sm_qos_r99aim_to_max_sdu(U8 packed_sdu_size) /*@*/ | |
270 { | |
271 U16 result = 0; | |
272 | |
273 if (packed_sdu_size < (U8)PS_MAX_SDU_1502) { | |
274 result = (U16)packed_sdu_size * (U16)10; | |
275 } else if (packed_sdu_size == (U8)PS_MAX_SDU_1502) { | |
276 result = (U16)1502; | |
277 } else if (packed_sdu_size == (U8)PS_MAX_SDU_1510) { | |
278 result = (U16)1510; | |
279 } else if (packed_sdu_size == (U8)PS_MAX_SDU_1520) { | |
280 result = (U16)1520; | |
281 } else { /* Error handling ? */ | |
282 result = (U16)1520; | |
283 (void)TRACE_EVENT( "Warning: Packed max SDU size value > 153 (1520 octets)! Truncated..."); | |
284 } | |
285 return result; | |
286 } | |
287 | |
288 /* | |
289 * Helper function for converting "human readable" transfer delay values | |
290 * into packed 3G air interface equvalents. | |
291 * | |
292 * Parameters: Integer representation of the transfer delay | |
293 * Returns: Packed transfer delay value | |
294 * | |
295 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
296 */ | |
297 | |
298 static U8 sm_qos_xfer_delay_to_r99aim(U16 xfer_delay) /*@*/ | |
299 { | |
300 U8 result = (U8)0; | |
301 | |
302 if (xfer_delay == 0) { | |
303 result = (U8)0; | |
304 } else if (xfer_delay < (U16)10) { /* Make sure low values do not map to SUBSCRIBED */ | |
305 result = (U8)1; | |
306 } else if (xfer_delay <= (U16)150) { | |
307 /* 10 - 150ms map to values 1 - 15 @ 10ms increments. We round down. */ | |
308 result = (U8)(xfer_delay / 10); | |
309 } else if (xfer_delay <= (U16)1000) { | |
310 /* 200 - 950ms map to values 16 - 31 @ 50ms increments. | |
311 * Values not on boundaries are rounded down. | |
312 * Formula: result = (xfer_delay / 50) + (16 - (200 / 50)) */ | |
313 result = (U8)((xfer_delay + ((16 * 50) - 200)) / 50); | |
314 } else if (xfer_delay <= (U16)4000) { | |
315 /* 1000 - 4000ms map to values 32-62 @ 100ms increments. | |
316 * Values not on boundaries are rounded down. | |
317 * Formula: result = (xfer_delay / 100) + (32 - (1000 / 100)) */ | |
318 result = (U8)((xfer_delay + ((32 * 100) - 1000)) / 100); | |
319 } else { | |
320 /* Error */ | |
321 (void)TRACE_EVENT( "Warning: Transfer delay out of bounds! Truncated..." ); | |
322 result = (U8)62; | |
323 } | |
324 return result; | |
325 } | |
326 | |
327 /* | |
328 * Helper function for converting packed 3G air interface transfer delay values | |
329 * into "human readable" equvalents. | |
330 * | |
331 * Parameters: Packed transfer delay value | |
332 * Returns: Integer representation of the transfer delay | |
333 * | |
334 * Conversion rules according to [3G 24.008, sec 11.5.6.5] | |
335 */ | |
336 | |
337 static U16 sm_qos_r99aim_to_xfer_delay(U8 packed_xfer_delay) /*@*/ | |
338 { | |
339 U16 result = 0; | |
340 | |
341 if (packed_xfer_delay == (U8)0) { | |
342 result = (U16)PS_XFER_DELAY_SUB; | |
343 } else if (packed_xfer_delay < (U8)16) { | |
344 result = (U16)packed_xfer_delay * (U16)10; | |
345 } else if (packed_xfer_delay < (U8)32) { | |
346 result = ((U16)packed_xfer_delay - (U16)12) * (U16)50; | |
347 } else if (packed_xfer_delay < (U8)63) { | |
348 result = ((U16)packed_xfer_delay - (U16)22) * (U16)100; | |
349 } else { | |
350 result = (U16)4000; | |
351 (void)TRACE_EVENT( "Warning: R99 transfer delay parameter out of bounds (== 63)! Truncated..." ); | |
352 } | |
353 | |
354 return result; | |
355 } | |
356 | |
357 /* | |
358 * Helper function for converting packed 3G air interface traffic class values | |
359 * into AT command equivalents as per [3G 27.007]. | |
360 * | |
361 * Parameters: Packed traffic class value | |
362 * Returns: AT command representation of the same traffic class value | |
363 */ | |
364 static U8 sm_qos_r99aim_to_tc(U8 packed_tc) /*@*/ | |
365 { | |
366 switch (packed_tc) { | |
367 case M_SM_QOS_TC_CONV: return (U8)PS_TC_CONV; | |
368 case M_SM_QOS_TC_STREAM: return (U8)PS_TC_STREAM; | |
369 case M_SM_QOS_TC_INTER: return (U8)PS_TC_INTER; | |
370 case M_SM_QOS_TC_BG: return (U8)PS_TC_BG; | |
371 default: | |
372 (void)TRACE_EVENT_P1("Warning: AIM traffic class '%d' out of bounds! Defaulting to SUBSCRIBED...", packed_tc); | |
373 return (U8)PS_TC_SUB; | |
374 } | |
375 } | |
376 | |
377 /* | |
378 * Helper function for converting AT command traffic class values | |
379 * into packed 3G air interface equivalents. | |
380 * | |
381 * Parameters: AT command traffic class value | |
382 * Returns: 3G AIM representation of the same traffic class value | |
383 */ | |
384 static U8 sm_qos_tc_to_r99aim(U8 tc) /*@*/ | |
385 { | |
386 switch (tc) { | |
387 case PS_TC_CONV: return (U8)M_SM_QOS_TC_CONV; | |
388 case PS_TC_STREAM: return (U8)M_SM_QOS_TC_STREAM; | |
389 case PS_TC_INTER: return (U8)M_SM_QOS_TC_INTER; | |
390 case PS_TC_BG: return (U8)M_SM_QOS_TC_BG; | |
391 case PS_TC_SUB: return (U8)M_SM_QOS_TC_SUB; | |
392 default: | |
393 (void)TRACE_EVENT_P1("ERROR: QoS traffic class '%d' out of bounds! Defaulting to SUBSCRIBED, but expect an imminent crash!", tc); | |
394 return (U8)M_SM_QOS_TC_SUB; | |
395 } | |
396 } | |
397 | |
398 /* | |
399 * Helper function for converting packed 3G air interface delivery order | |
400 * parameter values into AT command equivalents as per [3G 27.007]. | |
401 * | |
402 * Parameters: Packed delivery order parameter | |
403 * Returns: AT command representation of the same delivery order value | |
404 */ | |
405 static U8 sm_qos_r99aim_to_order(U8 packed_order) /*@*/ | |
406 { | |
407 switch (packed_order) { | |
408 case M_SM_QOS_ORDER_NO: return (U8)PS_ORDER_NO; | |
409 case M_SM_QOS_ORDER_YES: return (U8)PS_ORDER_YES; | |
410 default: | |
411 (void)TRACE_EVENT_P1("Warning: AIM delivery order parameter '%d' out of bounds! Defaulting to SUBSCRIBED...", packed_order); | |
412 return (U8)PS_ORDER_SUB; | |
413 } | |
414 } | |
415 | |
416 /* | |
417 * Helper function for converting AT command delivery order parameter values | |
418 * into packed 3G air interface equivalents. | |
419 * | |
420 * Parameters: AT command delivery order parameter | |
421 * Returns: Packed 3G AIM representation of the same delivery order value | |
422 */ | |
423 static U8 sm_qos_order_to_r99aim(U8 order) /*@*/ | |
424 { | |
425 switch (order) { | |
426 case PS_ORDER_NO: return (U8)M_SM_QOS_ORDER_NO; | |
427 case PS_ORDER_YES: return (U8)M_SM_QOS_ORDER_YES; | |
428 case PS_ORDER_SUB: return (U8)M_SM_QOS_ORDER_SUB; | |
429 default: | |
430 (void)TRACE_EVENT_P1("Warning: Delivery order parameter '%d' out of bounds! Defaulting to SUBSCRIBED...", order); | |
431 return (U8)M_SM_QOS_ORDER_SUB; | |
432 } | |
433 } | |
434 | |
435 /* | |
436 * Helper function for converting packed 3G air interface "delivery of | |
437 * erroneous SDUs" parameter values into AT command equivalents as per | |
438 * [3G 27.007]. | |
439 * | |
440 * Parameters: Packed delivery parameter | |
441 * Returns: AT command representation of the same delivery parameter | |
442 */ | |
443 static U8 sm_qos_r99aim_to_del_err_sdu(U8 packed_del_err_sdu) /*@*/ | |
444 { | |
445 switch (packed_del_err_sdu) { | |
446 case M_SM_QOS_DEL_ERR_NO: return (U8)PS_DEL_ERR_NO; | |
447 case M_SM_QOS_DEL_ERR_YES: return (U8)PS_DEL_ERR_YES; | |
448 case M_SM_QOS_DEL_ERR_NODETECT: return (U8)PS_DEL_ERR_NODETECT; | |
449 default: | |
450 (void)TRACE_EVENT_P1("Warning: AIM delivery of err SDU parameter '%d' out of bounds! Defaulting to SUBSCRIBED", packed_del_err_sdu); | |
451 return (U8)PS_DEL_ERR_SUB; | |
452 } | |
453 } | |
454 | |
455 /* | |
456 * Helper function for converting AT command "delivery of erroneous SDUs" | |
457 * parameter values into packed 3G air interface equivalents. | |
458 * | |
459 * Parameters: AT command delivery parameter | |
460 * Returns: Packed 3G AIM representation of the same delivery value | |
461 */ | |
462 static U8 sm_qos_del_err_sdu_to_r99aim(U8 del_err_sdu) /*@*/ | |
463 { | |
464 switch (del_err_sdu) { | |
465 case PS_DEL_ERR_NO: return (U8)M_SM_QOS_DEL_ERR_NO; | |
466 case PS_DEL_ERR_YES: return (U8)M_SM_QOS_DEL_ERR_YES; | |
467 case PS_DEL_ERR_NODETECT: return (U8)M_SM_QOS_DEL_ERR_NODETECT; | |
468 case PS_DEL_ERR_SUB: return (U8)M_SM_QOS_DEL_ERR_SUB; | |
469 default: | |
470 (void)TRACE_EVENT_P1("Warning: Delivery of err SDU parameter '%d' out of bounds! Defaulting to SUBSCRIBED...", del_err_sdu); | |
471 return (U8)M_SM_QOS_DEL_ERR_SUB; | |
472 } | |
473 } | |
474 | |
475 /* | |
476 * Function for converting a R97 QoS parameter set in SM internal representation | |
477 * into a 3G air message QoS parameter set. | |
478 * | |
479 * Conversion rules according to [3G 24.008, sec 10.5.6.5] | |
480 * | |
481 * Parameters: Originating R97 SM QoS parameter struct | |
482 * Destination R97/R99 3G QoS parameter struct (overwritten in this function) | |
483 */ | |
484 | |
485 static void sm_qos_convert_r97_to_aim(/*@in@*/ T_PS_qos_r97 *src_qos_r97, | |
486 /*@out@*/T_M_SM_qos *dst_qos) | |
487 /*@modifies dst_qos->qos_r97@*/ | |
488 { | |
489 #ifdef DEBUG_VERBOSE | |
490 (void)TRACE_FUNCTION( "sm_qos_convert_r97_to_aim" ); | |
491 #endif | |
492 | |
493 dst_qos->qos_r97.delay = src_qos_r97->delay; | |
494 dst_qos->qos_r97.reliability = src_qos_r97->relclass; | |
495 dst_qos->qos_r97.peak = src_qos_r97->peak; | |
496 dst_qos->qos_r97.precedence = src_qos_r97->preced; | |
497 dst_qos->qos_r97.mean = src_qos_r97->mean; | |
498 } | |
499 | |
500 static void sm_qos_convert_r97aim_to_r97(/*@in@*/ T_M_SM_qos_r97 *src_qos, | |
501 /*@out@*/T_PS_qos_r97 *dst_qos_r97) | |
502 /*@modifies dst_qos_r97@*/ | |
503 { | |
504 #ifdef DEBUG_VERBOSE | |
505 (void)TRACE_FUNCTION( "sm_qos_convert_r97aim_to_r97" ); | |
506 #endif | |
507 | |
508 dst_qos_r97->delay = src_qos->delay; | |
509 dst_qos_r97->relclass = src_qos->reliability; | |
510 dst_qos_r97->peak = src_qos->peak; | |
511 dst_qos_r97->preced = src_qos->precedence; | |
512 dst_qos_r97->mean = src_qos->mean; | |
513 } | |
514 | |
515 /* | |
516 * Function for converting a R99 QoS parameter set in SM internal representation | |
517 * into a 3G air message QoS parameter set. | |
518 * | |
519 * Conversion rules according to [3G 24.008, sec 10.5.6.5] | |
520 * | |
521 * Parameters: Originating R99 SM QoS parameter struct | |
522 * Destination R99 3G QoS parameter struct (overwritten in this function) | |
523 */ | |
524 | |
525 static void sm_qos_convert_r99_to_aim(/*@in@*/ T_PS_qos_r99 *src_qos_r99, | |
526 /*@out@*/T_M_SM_qos *dst_qos) | |
527 /*@globals sm_qos_ber_table, sm_qos_sdu_err_ratio_table, sm_qos_ratio_table@*/ | |
528 /*@modifies dst_qos->qos_r99@*/ | |
529 { | |
530 #ifdef DEBUG_VERBOSE | |
531 (void)TRACE_FUNCTION( "sm_qos_convert_r99_to_aim" ); | |
532 #endif | |
533 | |
534 /* Traffic class */ | |
535 dst_qos->qos_r99.tc = sm_qos_tc_to_r99aim(src_qos_r99->tc); | |
536 | |
537 /* Delivery order */ | |
538 dst_qos->qos_r99.order = sm_qos_order_to_r99aim(src_qos_r99->order); | |
539 | |
540 /* Delivery of erroneous SDUs */ | |
541 dst_qos->qos_r99.del_err_sdu = sm_qos_del_err_sdu_to_r99aim(src_qos_r99->del_err_sdu); | |
542 | |
543 /* Max SDU size */ | |
544 dst_qos->qos_r99.max_sdu = sm_qos_max_sdu_to_r99aim(src_qos_r99->max_sdu); | |
545 | |
546 /* Max uplink bit-rate */ | |
547 dst_qos->qos_r99.max_br_ul = sm_qos_bitrate_to_r99aim(src_qos_r99->max_rate_ul); | |
548 | |
549 /* Max downlink bit-rate */ | |
550 dst_qos->qos_r99.max_br_dl = sm_qos_bitrate_to_r99aim(src_qos_r99->max_rate_dl); | |
551 | |
552 /* Residual BER */ | |
553 dst_qos->qos_r99.ber = sm_qos_ratio_to_r99aim(sm_qos_ber_table, | |
554 src_qos_r99->ber.ratio_mant, | |
555 src_qos_r99->ber.ratio_exp); | |
556 | |
557 /* SDU error ratio */ | |
558 dst_qos->qos_r99.sdu_err_ratio = sm_qos_ratio_to_r99aim(sm_qos_sdu_err_ratio_table, | |
559 src_qos_r99->sdu_err_ratio.ratio_mant, | |
560 src_qos_r99->sdu_err_ratio.ratio_exp); | |
561 | |
562 /* Transfer delay */ | |
563 dst_qos->qos_r99.xfer_delay = sm_qos_xfer_delay_to_r99aim(src_qos_r99->xfer_delay); | |
564 | |
565 /* Traffic handling priority */ | |
566 dst_qos->qos_r99.handling_pri= src_qos_r99->handling_pri; | |
567 | |
568 /* Guaranteed uplink bit-rate */ | |
569 dst_qos->qos_r99.guar_br_ul = sm_qos_bitrate_to_r99aim(src_qos_r99->guar_br_ul); | |
570 | |
571 /* Guaranteed downlink bit-rate */ | |
572 dst_qos->qos_r99.guar_br_dl = sm_qos_bitrate_to_r99aim(src_qos_r99->guar_br_dl); | |
573 } | |
574 | |
575 /* | |
576 * Function for converting a R99 3G air message QoS parameter set into a | |
577 * R99 QoS parameter set in SM internal representation | |
578 * | |
579 * Conversion rules according to [3G 24.008, sec 10.5.6.5] | |
580 * | |
581 * Parameters: Originating R99 3G QoS parameter struct | |
582 * Destination R99 SM QoS parameter struct (overwritten in this function) | |
583 */ | |
584 | |
585 static void sm_qos_convert_r99aim_to_r99(/*@in@*/ T_M_SM_qos_r99 *src_qos_r99, | |
586 /*@out@*/T_PS_qos_r99 *dst_qos_r99) | |
587 /*@globals sm_qos_ber_table, sm_qos_sdu_err_ratio_table@*/ | |
588 /*@modifies dst_qos_r99@*/ | |
589 { | |
590 #ifdef DEBUG_VERBOSE | |
591 (void)TRACE_FUNCTION( "sm_qos_convert_r99aim_to_r99" ); | |
592 #endif | |
593 | |
594 /* Traffic class */ | |
595 dst_qos_r99->tc = sm_qos_r99aim_to_tc(src_qos_r99->tc); | |
596 | |
597 /* Delivery order */ | |
598 dst_qos_r99->order = sm_qos_r99aim_to_order(src_qos_r99->order); | |
599 | |
600 /* Delivery of erroneous SDUs */ | |
601 dst_qos_r99->del_err_sdu = sm_qos_r99aim_to_del_err_sdu(src_qos_r99->del_err_sdu); | |
602 | |
603 /* Max SDU size */ | |
604 dst_qos_r99->max_sdu = sm_qos_r99aim_to_max_sdu(src_qos_r99->max_sdu); | |
605 | |
606 /* Max uplink bit-rate */ | |
607 dst_qos_r99->max_rate_ul = sm_qos_r99aim_to_bitrate(src_qos_r99->max_br_ul); | |
608 | |
609 /* Max downlink bit-rate */ | |
610 dst_qos_r99->max_rate_dl = sm_qos_r99aim_to_bitrate(src_qos_r99->max_br_dl); | |
611 | |
612 /* Residual BER */ | |
613 sm_qos_r99aim_to_ratio(sm_qos_ber_table, src_qos_r99->ber, | |
614 &dst_qos_r99->ber.ratio_mant, | |
615 &dst_qos_r99->ber.ratio_exp); | |
616 | |
617 /* SDU error ratio */ | |
618 sm_qos_r99aim_to_ratio(sm_qos_sdu_err_ratio_table, src_qos_r99->sdu_err_ratio, | |
619 &dst_qos_r99->sdu_err_ratio.ratio_mant, | |
620 &dst_qos_r99->sdu_err_ratio.ratio_exp); | |
621 | |
622 /* Transfer delay */ | |
623 dst_qos_r99->xfer_delay = sm_qos_r99aim_to_xfer_delay(src_qos_r99->xfer_delay); | |
624 | |
625 /* Traffic handling priority */ | |
626 dst_qos_r99->handling_pri = src_qos_r99->handling_pri; | |
627 | |
628 /* Guaranteed uplink bit-rate */ | |
629 dst_qos_r99->guar_br_ul = sm_qos_r99aim_to_bitrate(src_qos_r99->guar_br_ul); | |
630 | |
631 /* Guaranteed downlink bit-rate */ | |
632 dst_qos_r99->guar_br_dl = sm_qos_r99aim_to_bitrate(src_qos_r99->guar_br_dl); | |
633 } | |
634 | |
635 /*==== PUBLIC FUNCTIONS =====================================================*/ | |
636 | |
637 /* | |
638 * Function for extracting the traffic class element stored for | |
639 * the given context. | |
640 */ | |
641 U8 sm_qos_get_traffic_class(struct T_SM_CONTEXT_DATA *context) | |
642 { | |
643 /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */ | |
644 TRACE_ASSERT(context != NULL); | |
645 | |
646 if (context->requested_qos.ctrl_qos == PS_is_R97) { | |
647 T_PS_qos_r99 temp_qos; | |
648 | |
649 (void)cl_qos_convert_r97_to_r99(&context->requested_qos.qos.qos_r97, | |
650 &temp_qos); | |
651 | |
652 return temp_qos.tc; | |
653 } | |
654 else if (context->requested_qos.ctrl_qos == PS_is_R99) { | |
655 return context->requested_qos.qos.qos_r99.tc; | |
656 } | |
657 else { | |
658 /* Default to SUBSCRIBED */ | |
659 return (U8)PS_TC_SUB; | |
660 } | |
661 } | |
662 | |
663 /* | |
664 +------------------------------------------------------------------------------ | |
665 | Function : sm_qos_convert_to_aim | |
666 +------------------------------------------------------------------------------ | |
667 | Description : Function for converting a QoS parameter set in internal SM | |
668 | representation into an air interface QoS parameter set. | |
669 | Handles both R97 and R99 types, skipping R99 elements if | |
670 | network is R97. | |
671 | | |
672 | Parameters : src_qos - Source QoS (internal representation) | |
673 | dst_qos - Destination air interface QoS structure | |
674 | release - Core network release (R97/R99) | |
675 +------------------------------------------------------------------------------ | |
676 */ | |
677 void sm_qos_convert_to_aim(/*@in@*/ T_SM_qos *src_qos, | |
678 /*@out@*/T_M_SM_qos *dst_qos, | |
679 T_PS_sgsn_rel release) | |
680 /*@globals sm_qos_ber_table, sm_qos_sdu_err_ratio_table, sm_qos_ratio_table@*/ | |
681 { | |
682 | |
683 #ifdef DEBUG_VERBOSE | |
684 (void)TRACE_FUNCTION("sm_qos_convert_to_aim"); | |
685 #endif | |
686 | |
687 /* Is SGSN release = pre-R99 (or R98 and older) ? */ | |
688 if (release == PS_SGSN_98_OLDER) { | |
689 if (src_qos->ctrl_qos == PS_is_R97) { | |
690 sm_qos_convert_r97_to_aim(&src_qos->qos.qos_r97, dst_qos); | |
691 } else if (src_qos->ctrl_qos == PS_is_R99) { | |
692 /* Convert R99 to R97 values */ | |
693 T_PS_qos_r97 tmp_qos_r97; | |
694 cl_qos_convert_r99_to_r97(&src_qos->qos.qos_r99, &tmp_qos_r97); | |
695 sm_qos_convert_r97_to_aim(&tmp_qos_r97, dst_qos); | |
696 } else { | |
697 (void)TRACE_ERROR( "Invalid ctrl_qos value!" ); | |
698 } | |
699 /* Do not include R99 QoS elements in air interface message */ | |
700 dst_qos->v_qos_r99 = (U8)FALSE; | |
701 dst_qos->tlv_len = (U8)M_SM_SIZE_R97_QOS; | |
702 } else if (release == PS_SGSN_99_ONWARDS) { | |
703 if (src_qos->ctrl_qos == PS_is_R97) { | |
704 T_PS_qos_r99 tmp_qos; | |
705 /* Convert R97 to R99 struct */ | |
706 (void)cl_qos_convert_r97_to_r99(&src_qos->qos.qos_r97, &tmp_qos); | |
707 /* Include both R97 and R99 QoS info in AIM */ | |
708 sm_qos_convert_r97_to_aim(&src_qos->qos.qos_r97, dst_qos); | |
709 sm_qos_convert_r99_to_aim(&tmp_qos, dst_qos); | |
710 } else if (src_qos->ctrl_qos == PS_is_R99) { | |
711 T_PS_qos_r97 tmp_qos_r97; | |
712 /* Fill in R99 AIM fields */ | |
713 sm_qos_convert_r99_to_aim(&src_qos->qos.qos_r99, dst_qos); | |
714 /* [3G 24.008] says to always include R97/R98 parameters in QoS IE */ | |
715 cl_qos_convert_r99_to_r97(&src_qos->qos.qos_r99, &tmp_qos_r97); | |
716 sm_qos_convert_r97_to_aim(&tmp_qos_r97, dst_qos); | |
717 } else { | |
718 (void)TRACE_ERROR( "Invalid ctrl_qos value!" ); | |
719 } | |
720 /* Include R99 QoS elements in air interface message */ | |
721 dst_qos->v_qos_r99 = (U8)TRUE; | |
722 dst_qos->tlv_len = (U8)M_SM_SIZE_R99_QOS; | |
723 } else { | |
724 (void)TRACE_EVENT_P1("ERROR: Invalid network release union controller %d!", | |
725 release); | |
726 } | |
727 } | |
728 | |
729 /* | |
730 +------------------------------------------------------------------------------ | |
731 | Function : sm_qos_assign_from_aim | |
732 +------------------------------------------------------------------------------ | |
733 | Description : Function for converting an air interface QoS parameter set | |
734 | to internal SM representation. Handles both R97 and R99 types, | |
735 | and sets the destination QoS union controller to the R97/R99 | |
736 | type of the air interface message. | |
737 | | |
738 | Parameters : dst_qos - Destination QoS (internal representation) | |
739 | src_qos - Source air interface QoS structure | |
740 +------------------------------------------------------------------------------ | |
741 */ | |
742 void sm_qos_assign_from_aim(/*@out@*/T_SM_qos *dst_qos, | |
743 /*@in@*/ T_M_SM_qos *src_qos) | |
744 /*@globals sm_qos_ber_table, sm_qos_sdu_err_ratio_table@*/ | |
745 { | |
746 #ifdef DEBUG_VERBOSE | |
747 (void)TRACE_FUNCTION( "sm_qos_assign_from_aim"); | |
748 #endif | |
749 | |
750 /* Does QoS include R99 elements? */ | |
751 if (src_qos->v_qos_r99 == (U8)FALSE) { | |
752 /* FALSE == No R99 elements present; Set type to R97 */ | |
753 dst_qos->ctrl_qos = PS_is_R97; | |
754 sm_qos_convert_r97aim_to_r97(&src_qos->qos_r97, &dst_qos->qos.qos_r97); | |
755 } else { | |
756 /* TRUE == R99 elements present; Set type to R99 */ | |
757 dst_qos->ctrl_qos = PS_is_R99; | |
758 sm_qos_convert_r99aim_to_r99(&src_qos->qos_r99, &dst_qos->qos.qos_r99); | |
759 } | |
760 } | |
761 | |
762 /* | |
763 +------------------------------------------------------------------------------ | |
764 | Function : sm_qos_compare_r97_lt_r97 | |
765 +------------------------------------------------------------------------------ | |
766 | Description : Compares an R97 QoS structure with another (minimum) R97 QoS | |
767 | structure in internal SM representation. Returns TRUE if | |
768 | the supplied QoS is *less than* minimum QoS. | |
769 | Parameters : cmp_qos_r97 - comparison QoS structure | |
770 | min_qos_r97 - minimum QoS structure | |
771 +------------------------------------------------------------------------------ | |
772 */ | |
773 /* NOTE: Removed. sm-to-sm comparisons only occur during MO modify | |
774 * procedures, which are not possible in R97.*/ | |
775 #if 0 | |
776 static BOOL sm_qos_compare_r97_lt_r97(/*@in@*/T_PS_qos_r97 *cmp_qos_r97, | |
777 /*@in@*/T_PS_qos_r97 *min_qos_r97) | |
778 { | |
779 (void)TRACE_FUNCTION( "sm_qos_compare_r97aim_lt_r97"); | |
780 | |
781 if (min_qos_r97->delay != (U8)NAS_DELAY_SUB && | |
782 cmp_qos_r97->delay > min_qos_r97->delay) | |
783 { | |
784 (void)TRACE_EVENT_P2("R97 DELAY parameter insufficient: %d > %d (min_qos)", | |
785 cmp_qos_r97->delay, min_qos_r97->delay); | |
786 return TRUE; | |
787 } | |
788 if (min_qos_r97->relclass != (U8)NAS_RELCLASS_SUB && | |
789 cmp_qos_r97->relclass > min_qos_r97->relclass) | |
790 { | |
791 (void)TRACE_EVENT_P2("R97 RELIABILITY CLASS parameter insufficient: " | |
792 "%d > %d (min_qos)", | |
793 cmp_qos_r97->relclass, min_qos_r97->relclass); | |
794 return TRUE; | |
795 } | |
796 if (min_qos_r97->peak != (U8)NAS_PEAK_SUB && | |
797 cmp_qos_r97->peak < min_qos_r97->peak) | |
798 { | |
799 (void)TRACE_EVENT_P2("R97 PEAK BITRATE parameter insufficient: " | |
800 "%d < %d (min_qos)", | |
801 cmp_qos_r97->peak, min_qos_r97->peak); | |
802 return TRUE; | |
803 } | |
804 if (min_qos_r97->preced != (U8)NAS_PRECED_SUB && | |
805 cmp_qos_r97->preced > min_qos_r97->preced) | |
806 { | |
807 (void)TRACE_EVENT_P2("R97 PRECEDENCE CLASS parameter insufficient: " | |
808 "%d > %d (min_qos)", | |
809 cmp_qos_r97->preced, min_qos_r97->preced); | |
810 return TRUE; | |
811 } | |
812 if (min_qos_r97->mean != (U8)NAS_MEAN_SUB && | |
813 cmp_qos_r97->mean < min_qos_r97->mean) | |
814 { | |
815 (void)TRACE_EVENT_P2("R97 MEAN BITRATE parameter insufficient: " | |
816 "%d < %d (min_qos)", | |
817 cmp_qos_r97->mean, min_qos_r97->mean); | |
818 return TRUE; | |
819 } | |
820 return FALSE; | |
821 } | |
822 #endif | |
823 | |
824 /* | |
825 +------------------------------------------------------------------------------ | |
826 | Function : sm_qos_compare_r99_lt_r99 | |
827 +------------------------------------------------------------------------------ | |
828 | Description : Compares an R99 QoS structure with a (minimum) R99 QoS | |
829 | structure in internal SM representation. Returns TRUE if | |
830 | comparison QoS is *less than* minimum QoS. | |
831 | Parameters : cmp_qos_r99 - air interface QoS structure | |
832 | min_qos_r99 - minimum QoS structure | |
833 +------------------------------------------------------------------------------ | |
834 */ | |
835 static BOOL sm_qos_compare_r99_lt_r99(/*@in@*/T_PS_qos_r99 *cmp_qos_r99, | |
836 /*@in@*/T_PS_qos_r99 *min_qos_r99) | |
837 { | |
838 T_PS_tc traffic_class = (T_PS_tc)cmp_qos_r99->tc; | |
839 #ifdef DEBUG_VERBOSE | |
840 (void)TRACE_FUNCTION( "sm_qos_compare_r99_lt_r99"); | |
841 #endif | |
842 | |
843 /* Traffic class */ | |
844 if ((min_qos_r99->tc != (U8)PS_TC_SUB) && | |
845 (cmp_qos_r99->tc > min_qos_r99->tc)) | |
846 { | |
847 (void)TRACE_EVENT_P2("R99 TRAFFIC CLASS parameter insufficient: " | |
848 "%d > %d (min_qos)", | |
849 cmp_qos_r99->tc, min_qos_r99->tc); | |
850 return TRUE; | |
851 } | |
852 | |
853 /* Delivery order */ | |
854 if ((min_qos_r99->order != (U8)PS_ORDER_SUB) && | |
855 (cmp_qos_r99->order != min_qos_r99->order)) | |
856 { | |
857 (void)TRACE_EVENT_P2("R99 DELIVERY ORDER parameter insufficient: " | |
858 "%d != %d (min_qos)", | |
859 cmp_qos_r99->order, min_qos_r99->order); | |
860 return TRUE; | |
861 } | |
862 | |
863 /* Delivery of erroneous SDUs */ | |
864 if ((min_qos_r99->del_err_sdu != (U8)PS_DEL_ERR_SUB) && | |
865 (cmp_qos_r99->del_err_sdu != min_qos_r99->del_err_sdu)) | |
866 { | |
867 (void)TRACE_EVENT_P2("R99 DELIVERY of ERRONEUOS SDUs parameter " | |
868 "insufficient: %d != %d (min_qos)", | |
869 cmp_qos_r99->del_err_sdu, min_qos_r99->del_err_sdu); | |
870 return TRUE; | |
871 } | |
872 | |
873 /* Max SDU size */ | |
874 if ((min_qos_r99->max_sdu != (U16)PS_MAX_SDU_SUB) && | |
875 (cmp_qos_r99->max_sdu < min_qos_r99->max_sdu)) | |
876 { | |
877 (void)TRACE_EVENT_P2("R99 MAX SDU SIZE parameter insufficient: " | |
878 "%d < %d (min_qos)", | |
879 cmp_qos_r99->max_sdu, min_qos_r99->max_sdu); | |
880 return TRUE; | |
881 } | |
882 | |
883 /* Max uplink bit-rate */ | |
884 if ((min_qos_r99->max_rate_ul != (U16)PS_MAX_BR_UL_SUB) && | |
885 (cmp_qos_r99->max_rate_ul < min_qos_r99->max_rate_ul)) | |
886 { | |
887 (void)TRACE_EVENT_P2("R99 MAX UPLINK BITRATE parameter insufficient: " | |
888 "%d < %d (min_qos)", | |
889 cmp_qos_r99->max_rate_ul, min_qos_r99->max_rate_ul); | |
890 return TRUE; | |
891 } | |
892 | |
893 /* Max downlink bit-rate */ | |
894 if ((min_qos_r99->max_rate_dl != (U16)PS_MAX_BR_DL_SUB) && | |
895 (cmp_qos_r99->max_rate_dl < min_qos_r99->max_rate_dl)) | |
896 { | |
897 (void)TRACE_EVENT_P2("R99 MAX DOWNLINK BITRATE parameter insufficient: " | |
898 "%d < %d (min_qos)", | |
899 cmp_qos_r99->max_rate_dl, min_qos_r99->max_rate_dl); | |
900 return TRUE; | |
901 } | |
902 | |
903 /* Residual BER */ | |
904 if ((min_qos_r99->ber.ratio_exp != (U8)0 | |
905 && min_qos_r99->ber.ratio_mant != (U8)0) && | |
906 (sm_qos_ratio_to_U32(cmp_qos_r99->ber.ratio_mant, | |
907 cmp_qos_r99->ber.ratio_exp) < | |
908 sm_qos_ratio_to_U32(min_qos_r99->ber.ratio_mant, | |
909 min_qos_r99->ber.ratio_exp))) | |
910 { | |
911 (void)TRACE_EVENT_P4("R99 RESIDUAL BIT ERROR RATE parameter insufficient: " | |
912 "%dE-%d < %dE-%d (min_qos)", | |
913 cmp_qos_r99->ber.ratio_mant, | |
914 cmp_qos_r99->ber.ratio_exp, | |
915 min_qos_r99->ber.ratio_mant, | |
916 min_qos_r99->ber.ratio_exp); | |
917 return TRUE; | |
918 } | |
919 | |
920 /* SDU error ratio */ | |
921 if ((min_qos_r99->sdu_err_ratio.ratio_exp != (U8)0 && | |
922 min_qos_r99->sdu_err_ratio.ratio_mant != (U8)0) && | |
923 (sm_qos_ratio_to_U32(cmp_qos_r99->sdu_err_ratio.ratio_mant, | |
924 cmp_qos_r99->sdu_err_ratio.ratio_exp) < | |
925 sm_qos_ratio_to_U32(min_qos_r99->sdu_err_ratio.ratio_mant, | |
926 min_qos_r99->sdu_err_ratio.ratio_exp))) | |
927 { | |
928 (void)TRACE_EVENT_P4("R99 SDU ERROR RATIO parameter insufficient: " | |
929 "%dE-%d < %dE-%d (min_qos)", | |
930 cmp_qos_r99->sdu_err_ratio.ratio_mant, | |
931 cmp_qos_r99->sdu_err_ratio.ratio_exp, | |
932 min_qos_r99->sdu_err_ratio.ratio_mant, | |
933 min_qos_r99->sdu_err_ratio.ratio_exp); | |
934 return TRUE; | |
935 } | |
936 | |
937 /* Transfer delay - Note! Only for real-time traffic class traffic! */ | |
938 if ((traffic_class == PS_TC_CONV || traffic_class == PS_TC_STREAM) && | |
939 (min_qos_r99->xfer_delay != (U16)PS_XFER_DELAY_SUB) && | |
940 (cmp_qos_r99->xfer_delay > min_qos_r99->xfer_delay)) | |
941 { | |
942 (void)TRACE_EVENT_P2("R99 TRANSFER DELAY parameter insufficient: " | |
943 "%d > %d (min_qos)", | |
944 cmp_qos_r99->xfer_delay, min_qos_r99->xfer_delay); | |
945 return TRUE; | |
946 } | |
947 | |
948 /* Traffic handling priority - Note: Only interactive traffic class! */ | |
949 if ((traffic_class == PS_TC_INTER) && | |
950 (min_qos_r99->handling_pri != (U8)PS_HANDLING_PRI_SUB) && | |
951 (cmp_qos_r99->handling_pri > min_qos_r99->handling_pri)) | |
952 { | |
953 (void)TRACE_EVENT_P2("R99 TRANSFER HANDLING PRIORITY parameter " | |
954 "insufficient: %d > %d (min_qos)", | |
955 cmp_qos_r99->handling_pri, min_qos_r99->handling_pri); | |
956 return TRUE; | |
957 } | |
958 | |
959 /* Guaranteed uplink bit-rate - Note: Only for real-time traffic class traffic! */ | |
960 if ((traffic_class == PS_TC_CONV || traffic_class == PS_TC_STREAM) && | |
961 (min_qos_r99->guar_br_ul != (U16)PS_GUAR_BR_UL_SUB) && | |
962 (cmp_qos_r99->guar_br_ul < min_qos_r99->guar_br_ul)) | |
963 { | |
964 (void)TRACE_EVENT_P2("R99 GUARANTEED UPLINK BITRATE parameter " | |
965 "insufficient: %d < %d (min_qos)", | |
966 cmp_qos_r99->guar_br_ul, min_qos_r99->guar_br_ul); | |
967 return TRUE; | |
968 } | |
969 | |
970 /* Guaranteed downlink bit-rate - Note: Only for real-time traffic class traffic! */ | |
971 if ((traffic_class == PS_TC_CONV || traffic_class == PS_TC_STREAM) && | |
972 (min_qos_r99->guar_br_dl != (U16)PS_GUAR_BR_DL_SUB) && | |
973 (cmp_qos_r99->guar_br_dl < min_qos_r99->guar_br_dl)) | |
974 { | |
975 (void)TRACE_EVENT_P2("R99 GUARANTEED DOWNLINK BITRATE parameter " | |
976 "insufficient: %d < %d (min_qos)", | |
977 cmp_qos_r99->guar_br_dl, min_qos_r99->guar_br_dl); | |
978 return TRUE; | |
979 } | |
980 | |
981 return FALSE; | |
982 } | |
983 | |
984 /* | |
985 +------------------------------------------------------------------------------ | |
986 | Function : sm_qos_compare_r97aim_lt_r97 | |
987 +------------------------------------------------------------------------------ | |
988 | Description : Compares an R97 air interface QoS structure with an R97 QoS | |
989 | structure in internal SM representation. Returns TRUE if | |
990 | AIM QoS is *less than* min QoS or *greater than* req QoS. | |
991 | Parameters : aim_qos_r97 - air interface QoS structure | |
992 | min_qos_r97 - minimum QoS structure | |
993 | req_qos_r97 - requested QoS structure | |
994 +------------------------------------------------------------------------------ | |
995 */ | |
996 static BOOL sm_qos_compare_r97aim_lt_r97(/*@in@*/T_M_SM_qos_r97 *aim_qos_r97, | |
997 /*@in@*/T_PS_qos_r97 *min_qos_r97, | |
998 /*@in@*/T_PS_qos_r97 *req_qos_r97 ) | |
999 { | |
1000 (void)TRACE_FUNCTION( "sm_qos_compare_r97aim_lt_r97"); | |
1001 | |
1002 /* Compare R97 AIM QoS with R97 parameter struct */ | |
1003 if ( (min_qos_r97->delay != (U8)PS_DELAY_SUB && | |
1004 aim_qos_r97->delay > min_qos_r97->delay ) || | |
1005 (req_qos_r97->delay != (U8)PS_DELAY_SUB && | |
1006 aim_qos_r97->delay < req_qos_r97->delay) ) | |
1007 { | |
1008 (void)TRACE_EVENT_P4("R97 DELAY parameter insufficient: " | |
1009 "%d > %d (min_qos) || %d < %d (req_qos)", | |
1010 aim_qos_r97->delay, min_qos_r97->delay, \ | |
1011 aim_qos_r97->delay, req_qos_r97->delay); | |
1012 return TRUE; | |
1013 } | |
1014 if ( (min_qos_r97->relclass != (U8)PS_RELCLASS_SUB && | |
1015 aim_qos_r97->reliability > min_qos_r97->relclass) || | |
1016 (req_qos_r97->relclass != (U8)PS_RELCLASS_SUB && | |
1017 aim_qos_r97->reliability < req_qos_r97->relclass) && | |
1018 /*the following line is for the TC 46.1.2.2.1.2*/ | |
1019 !((aim_qos_r97->reliability ==2) && (req_qos_r97->relclass == 5)) ) | |
1020 { | |
1021 (void)TRACE_EVENT_P4("R97 RELIABILITY CLASS parameter insufficient: " | |
1022 "%d > %d (min_qos) %d < %d (req_qos)", | |
1023 aim_qos_r97->reliability, min_qos_r97->relclass, \ | |
1024 aim_qos_r97->reliability, req_qos_r97->relclass); | |
1025 return TRUE; | |
1026 } | |
1027 if ( (min_qos_r97->peak != (U8)PS_PEAK_SUB && | |
1028 aim_qos_r97->peak < min_qos_r97->peak) || | |
1029 (req_qos_r97->peak != (U8)PS_PEAK_SUB && | |
1030 aim_qos_r97->peak > req_qos_r97->peak) ) | |
1031 { | |
1032 (void)TRACE_EVENT_P4("R97 PEAK BITRATE parameter insufficient: " | |
1033 "%d < %d (min_qos) || %d > %d (req_qos)", | |
1034 aim_qos_r97->peak, min_qos_r97->peak, \ | |
1035 aim_qos_r97->peak, req_qos_r97->peak); | |
1036 return TRUE; | |
1037 } | |
1038 if ( (min_qos_r97->preced != (U8)PS_PRECED_SUB && | |
1039 aim_qos_r97->precedence > min_qos_r97->preced) || | |
1040 (req_qos_r97->preced != (U8)PS_PRECED_SUB && | |
1041 aim_qos_r97->precedence < req_qos_r97->preced)) | |
1042 { | |
1043 (void)TRACE_EVENT_P4("R97 PRECEDENCE CLASS parameter insufficient: " | |
1044 "%d > %d (min_qos) || %d < %d (req_qos)", | |
1045 aim_qos_r97->precedence, min_qos_r97->preced, \ | |
1046 aim_qos_r97->precedence, req_qos_r97->preced); | |
1047 return TRUE; | |
1048 } | |
1049 if ( (min_qos_r97->mean != (U8)PS_MEAN_SUB && | |
1050 aim_qos_r97->mean < min_qos_r97->mean) || | |
1051 (req_qos_r97->mean != (U8)PS_MEAN_SUB && | |
1052 aim_qos_r97->mean > req_qos_r97->mean) ) | |
1053 { | |
1054 (void)TRACE_EVENT_P4("R97 MEAN BITRATE parameter insufficient: " | |
1055 "%d < %d (min_qos) || %d > %d (req_qos)", | |
1056 aim_qos_r97->mean, min_qos_r97->mean, \ | |
1057 aim_qos_r97->mean, req_qos_r97->mean); | |
1058 return TRUE; | |
1059 } | |
1060 | |
1061 return FALSE; | |
1062 } | |
1063 | |
1064 /* | |
1065 +------------------------------------------------------------------------------ | |
1066 | Function : sm_qos_compare_r99aim_lt_r99 | |
1067 +------------------------------------------------------------------------------ | |
1068 | Description : Compares an R99 air interface QoS structure with an R99 QoS | |
1069 | structure in internal SM representation. Returns TRUE if | |
1070 | AIM QoS is *less than* minimum QoS. | |
1071 | Parameters : aim_qos_r99 - air interface QoS structure | |
1072 | min_qos_r99 - minimum QoS structure | |
1073 +------------------------------------------------------------------------------ | |
1074 */ | |
1075 static BOOL sm_qos_compare_r99aim_lt_r99(/*@in@*/T_M_SM_qos_r99 *aim_qos_r99, | |
1076 /*@in@*/T_PS_qos_r99 *min_qos_r99) | |
1077 { | |
1078 (void)TRACE_FUNCTION( "sm_qos_compare_r99aim_lt_r99" ); | |
1079 | |
1080 /* Traffic class */ | |
1081 if ((min_qos_r99->tc != (U8)PS_TC_SUB) && | |
1082 (sm_qos_r99aim_to_tc(aim_qos_r99->tc) > min_qos_r99->tc)) | |
1083 { | |
1084 (void)TRACE_EVENT_P2("R99 TRAFFIC CLASS parameter insufficient: " | |
1085 "%d > %d (min_qos)", | |
1086 sm_qos_r99aim_to_tc(aim_qos_r99->tc), | |
1087 min_qos_r99->tc); | |
1088 return TRUE; | |
1089 } | |
1090 | |
1091 /* Delivery order */ | |
1092 if ((min_qos_r99->order != (U8)PS_ORDER_SUB) && | |
1093 (sm_qos_r99aim_to_order(aim_qos_r99->order) != min_qos_r99->order)) | |
1094 { | |
1095 (void)TRACE_EVENT_P2("R99 DELIVERY ORDER parameter insufficient: " | |
1096 "%d != %d (min_qos)", | |
1097 sm_qos_r99aim_to_order(aim_qos_r99->order), | |
1098 min_qos_r99->order); | |
1099 return TRUE; | |
1100 } | |
1101 | |
1102 /* Delivery of erroneous SDUs */ | |
1103 if ((min_qos_r99->del_err_sdu != (U8)PS_DEL_ERR_SUB) && | |
1104 (sm_qos_r99aim_to_del_err_sdu(aim_qos_r99->del_err_sdu) != min_qos_r99->del_err_sdu)) | |
1105 { | |
1106 (void)TRACE_EVENT_P2("R99 DELIVERY of ERRONEUOS SDUs parameter " | |
1107 "insufficient: %d != %d (min_qos)", | |
1108 sm_qos_r99aim_to_del_err_sdu(aim_qos_r99->del_err_sdu), | |
1109 min_qos_r99->del_err_sdu); | |
1110 return TRUE; | |
1111 } | |
1112 | |
1113 /* Max SDU size */ | |
1114 if ((min_qos_r99->max_sdu != (U16)PS_MAX_SDU_SUB) && | |
1115 (sm_qos_r99aim_to_max_sdu(aim_qos_r99->max_sdu) < min_qos_r99->max_sdu)) | |
1116 { | |
1117 (void)TRACE_EVENT_P2("R99 MAX SDU SIZE parameter insufficient: " | |
1118 "%d < %d (min_qos)", | |
1119 sm_qos_r99aim_to_max_sdu(aim_qos_r99->max_sdu), | |
1120 min_qos_r99->max_sdu); | |
1121 return TRUE; | |
1122 } | |
1123 | |
1124 /* Max uplink bit-rate */ | |
1125 if ((min_qos_r99->max_rate_ul != (U16)PS_MAX_BR_UL_SUB) && | |
1126 (sm_qos_r99aim_to_bitrate(aim_qos_r99->max_br_ul) < min_qos_r99->max_rate_ul)) | |
1127 { | |
1128 (void)TRACE_EVENT_P2("R99 MAX UPLINK BITRATE parameter insufficient: " | |
1129 "%d < %d (min_qos)", | |
1130 sm_qos_r99aim_to_bitrate(aim_qos_r99->max_br_ul), | |
1131 min_qos_r99->max_rate_ul); | |
1132 return TRUE; | |
1133 } | |
1134 | |
1135 /* Max downlink bit-rate */ | |
1136 if ((min_qos_r99->max_rate_dl != (U16)PS_MAX_BR_DL_SUB) && | |
1137 (sm_qos_r99aim_to_bitrate(aim_qos_r99->max_br_dl) < min_qos_r99->max_rate_dl)) | |
1138 { | |
1139 (void)TRACE_EVENT_P2("R99 MAX DOWNLINK BITRATE parameter insufficient: " | |
1140 "%d < %d (min_qos)", | |
1141 sm_qos_r99aim_to_bitrate(aim_qos_r99->max_br_ul), | |
1142 min_qos_r99->max_rate_dl); | |
1143 return TRUE; | |
1144 } | |
1145 | |
1146 /* Residual BER */ | |
1147 if ((min_qos_r99->ber.ratio_exp != (U8)0 | |
1148 && min_qos_r99->ber.ratio_mant != (U8)0) && | |
1149 (sm_qos_r99aim_ratio_to_U32(sm_qos_ber_table, aim_qos_r99->ber) < | |
1150 sm_qos_ratio_to_U32(min_qos_r99->ber.ratio_mant, | |
1151 min_qos_r99->ber.ratio_exp))) | |
1152 { | |
1153 #ifdef DEBUG | |
1154 U8 ratio_exp, ratio_mant; | |
1155 sm_qos_r99aim_to_ratio(sm_qos_ber_table, aim_qos_r99->ber, | |
1156 &ratio_mant, &ratio_exp); | |
1157 (void)TRACE_EVENT_P4("R99 RESIDUAL BIT ERROR RATE parameter insufficient: " | |
1158 "%dE-%d < %dE-%d (min_qos)", | |
1159 ratio_mant, ratio_exp, | |
1160 min_qos_r99->ber.ratio_mant, | |
1161 min_qos_r99->ber.ratio_exp); | |
1162 #endif | |
1163 return TRUE; | |
1164 } | |
1165 | |
1166 /* SDU error ratio */ | |
1167 if ((min_qos_r99->sdu_err_ratio.ratio_exp != (U8)0 && | |
1168 min_qos_r99->sdu_err_ratio.ratio_mant != (U8)0) && | |
1169 (sm_qos_r99aim_ratio_to_U32(sm_qos_sdu_err_ratio_table, aim_qos_r99->sdu_err_ratio) < | |
1170 sm_qos_ratio_to_U32(min_qos_r99->sdu_err_ratio.ratio_mant, | |
1171 min_qos_r99->sdu_err_ratio.ratio_exp))) | |
1172 { | |
1173 #ifdef DEBUG | |
1174 U8 ratio_exp, ratio_mant; | |
1175 sm_qos_r99aim_to_ratio(sm_qos_sdu_err_ratio_table, | |
1176 aim_qos_r99->sdu_err_ratio, | |
1177 &ratio_mant, &ratio_exp); | |
1178 (void)TRACE_EVENT_P4("R99 SDU ERROR RATIO parameter insufficient: " | |
1179 "%dE-%d < %dE-%d (min_qos)", | |
1180 ratio_mant, ratio_exp, | |
1181 min_qos_r99->sdu_err_ratio.ratio_mant, | |
1182 min_qos_r99->sdu_err_ratio.ratio_exp); | |
1183 #endif | |
1184 return TRUE; | |
1185 } | |
1186 | |
1187 /* Transfer delay - Note! Only for real-time traffic class traffic! */ | |
1188 if ((aim_qos_r99->tc == (U8)M_SM_QOS_TC_CONV | |
1189 || aim_qos_r99->tc == (U8)M_SM_QOS_TC_STREAM) && | |
1190 (min_qos_r99->xfer_delay != (U16)PS_XFER_DELAY_SUB) && | |
1191 (sm_qos_r99aim_to_xfer_delay(aim_qos_r99->xfer_delay) > min_qos_r99->xfer_delay)) | |
1192 { | |
1193 (void)TRACE_EVENT_P2("R99 TRANSFER DELAY parameter insufficient: " | |
1194 "%d > %d (min_qos)", | |
1195 sm_qos_r99aim_to_xfer_delay(aim_qos_r99->xfer_delay), | |
1196 min_qos_r99->xfer_delay); | |
1197 return TRUE; | |
1198 } | |
1199 | |
1200 /* Traffic handling priority - Note: Only interactive traffic class! */ | |
1201 if ((aim_qos_r99->tc == (U8)M_SM_QOS_TC_INTER) && | |
1202 (min_qos_r99->handling_pri != (U8)PS_HANDLING_PRI_SUB) && | |
1203 (aim_qos_r99->handling_pri > min_qos_r99->handling_pri)) | |
1204 { | |
1205 (void)TRACE_EVENT_P2("R99 TRANSFER HANDLING PRIORITY parameter " | |
1206 "insufficient: %d > %d (min_qos)", | |
1207 aim_qos_r99->handling_pri, min_qos_r99->handling_pri); | |
1208 return TRUE; | |
1209 } | |
1210 | |
1211 /* Guaranteed uplink bit-rate - Note: Only for real-time traffic class traffic! */ | |
1212 if ((aim_qos_r99->tc == (U8)M_SM_QOS_TC_CONV | |
1213 || aim_qos_r99->tc == (U8)M_SM_QOS_TC_STREAM) && | |
1214 (min_qos_r99->guar_br_ul != (U16)PS_GUAR_BR_UL_SUB) && | |
1215 (sm_qos_r99aim_to_bitrate(aim_qos_r99->guar_br_ul) < min_qos_r99->guar_br_ul)) | |
1216 { | |
1217 (void)TRACE_EVENT_P2("R99 GUARANTEED UPLINK BITRATE parameter " | |
1218 "insufficient: %d < %d (min_qos)", | |
1219 sm_qos_r99aim_to_bitrate(aim_qos_r99->guar_br_ul), | |
1220 min_qos_r99->guar_br_ul); | |
1221 return TRUE; | |
1222 } | |
1223 | |
1224 /* Guaranteed downlink bit-rate - Note: Only for real-time traffic class traffic! */ | |
1225 if ((aim_qos_r99->tc == (U8)M_SM_QOS_TC_CONV | |
1226 || aim_qos_r99->tc == (U8)M_SM_QOS_TC_STREAM) && | |
1227 (min_qos_r99->guar_br_dl != (U16)PS_GUAR_BR_DL_SUB) && | |
1228 (sm_qos_r99aim_to_bitrate(aim_qos_r99->guar_br_dl) < min_qos_r99->guar_br_dl)) | |
1229 { | |
1230 (void)TRACE_EVENT_P2("R99 GUARANTEED DOWNLINK BITRATE parameter " | |
1231 "insufficient: %d < %d (min_qos)", | |
1232 sm_qos_r99aim_to_bitrate(aim_qos_r99->guar_br_dl), | |
1233 min_qos_r99->guar_br_dl); | |
1234 return TRUE; | |
1235 } | |
1236 | |
1237 return FALSE; | |
1238 } | |
1239 | |
1240 /* | |
1241 +------------------------------------------------------------------------------ | |
1242 | Function : sm_qos_is_minimum_satisfied_by_aim | |
1243 +------------------------------------------------------------------------------ | |
1244 | Description : Main comparison function. Compares a 3G air interface message | |
1245 | QoS parameter set (R97 or R99) with the minimum QoS parameter | |
1246 | set in context data. | |
1247 | Returns TRUE if the 3G air message parameters are greater than | |
1248 | or equal to the minimum parameters in SM representation | |
1249 | ("greater than" is different for each value). | |
1250 | | |
1251 | Parameters : context - Context data | |
1252 | aim_qos - air interface QoS structure | |
1253 +------------------------------------------------------------------------------ | |
1254 */ | |
1255 BOOL sm_qos_is_minimum_satisfied_by_aim(struct T_SM_CONTEXT_DATA *context, | |
1256 T_M_SM_qos *aim_qos) | |
1257 { | |
1258 BOOL less_than = TRUE; | |
1259 | |
1260 #ifdef DEBUG_VERBOSE | |
1261 (void)TRACE_FUNCTION( "sm_qos_is_minimum_satisfied_by_aim"); | |
1262 #endif | |
1263 /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */ | |
1264 TRACE_ASSERT(context != NULL); | |
1265 | |
1266 if (context->minimum_qos.ctrl_qos == PS_is_qos_not_present) { | |
1267 /* Accept QoS without any checking */ | |
1268 return TRUE; | |
1269 } | |
1270 if (context->minimum_qos.ctrl_qos == PS_is_R97) { | |
1271 T_PS_qos_r97 *min_qos = &context->minimum_qos.qos.qos_r97; | |
1272 T_PS_qos_r97 *req_qos = &context->requested_qos.qos.qos_r97; | |
1273 if (aim_qos->v_qos_r99 == (U8)FALSE) { | |
1274 less_than = sm_qos_compare_r97aim_lt_r97(&aim_qos->qos_r97, min_qos, | |
1275 req_qos); | |
1276 } else { | |
1277 | |
1278 /* This #if.. #else part is required because we currently do not set | |
1279 * RAT when MMPM_ATTACH_IND is received. When the RAT is set properly | |
1280 * retain ONLY the #else part. | |
1281 */ | |
1282 /*#ifdef SM_EDGE */ /*ONLY FOR GPRS WORLD*/ | |
1283 /*In GPRS world try comparing only R97 part of QoS*/ | |
1284 TRACE_EVENT("GSM/GPRS RAT.. Comparing only R97 part of QoS."); | |
1285 less_than = sm_qos_compare_r97aim_lt_r97(&aim_qos->qos_r97, min_qos, | |
1286 req_qos); | |
1287 #if 0 | |
1288 /*#else*/ /*FOR UMTS and DUAL-MODE*/ | |
1289 if (sm_get_current_rat() == PS_RAT_GSM){ | |
1290 /*In GPRS world compare only R97 part of QoS*/ | |
1291 TRACE_EVENT("GSM/GPRS RAT.. Comparing only R97 part of QoS."); | |
1292 less_than = sm_qos_compare_r97aim_lt_r97(&aim_qos->qos_r97, min_qos, | |
1293 req_qos); | |
1294 } else { /*We should be in UMTS world now..*/ | |
1295 T_PS_qos_r99 tmp_qos; | |
1296 TRACE_EVENT("Calling cl_qos_convert_r97_to_r99() for min qos"); | |
1297 cl_qos_convert_r97_to_r99(&context->minimum_qos.qos.qos_r97, &tmp_qos); | |
1298 TRACE_EVENT("UMTS RAT.. Comparing only R99 part of QoS."); | |
1299 less_than = sm_qos_compare_r99aim_lt_r99(&aim_qos->qos_r99, &tmp_qos); | |
1300 } | |
1301 /*#endif*/ | |
1302 #endif | |
1303 | |
1304 } | |
1305 } | |
1306 else if (context->minimum_qos.ctrl_qos == PS_is_R99) { | |
1307 T_PS_qos_r99 tmp_qos; | |
1308 if (aim_qos->v_qos_r99 == (U8)FALSE) { | |
1309 cl_qos_convert_r97_to_r99(&context->minimum_qos.qos.qos_r97, &tmp_qos); | |
1310 } | |
1311 else { | |
1312 memcpy(&tmp_qos, &context->minimum_qos.qos.qos_r99, sizeof(T_PS_qos_r99)); | |
1313 } | |
1314 | |
1315 less_than = sm_qos_compare_r99aim_lt_r99(&aim_qos->qos_r99, &tmp_qos); | |
1316 } else { /* if (context->ctrl_minimum_qos) */ | |
1317 (void)TRACE_EVENT_P1("ERROR! Invalid union controller == %d in minimum QoS!", | |
1318 context->minimum_qos.ctrl_qos); | |
1319 } | |
1320 | |
1321 return !less_than; | |
1322 } | |
1323 | |
1324 /* | |
1325 +------------------------------------------------------------------------------ | |
1326 | Function : sm_qos_is_minimum_satisfied_by_aim | |
1327 +------------------------------------------------------------------------------ | |
1328 | Description : Comparison function. Compares a the minimum QoS parameter set | |
1329 | configured in context data with another QoS structure in | |
1330 | internal SM representation. Returns TRUE if the comparison QoS | |
1331 | parameters are greater than or equal to the minimum parameters. | |
1332 | ("greater than" is different for each value). | |
1333 | | |
1334 | Parameters : context - Context data | |
1335 | sm_qos - comparison QoS structure | |
1336 +------------------------------------------------------------------------------ | |
1337 */ | |
1338 BOOL sm_qos_is_minimum_satisfied_by_sm(struct T_SM_CONTEXT_DATA *context, | |
1339 T_SM_qos *sm_qos) | |
1340 { | |
1341 BOOL less_than = TRUE; | |
1342 | |
1343 #ifdef DEBUG_VERBOSE | |
1344 (void)TRACE_FUNCTION( "sm_qos_is_minimum_satisfied_by_sm"); | |
1345 #endif | |
1346 /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */ | |
1347 TRACE_ASSERT(context != NULL); | |
1348 | |
1349 if (context->minimum_qos.ctrl_qos == PS_is_qos_not_present) { | |
1350 /* Accept QoS without any checking */ | |
1351 return TRUE; | |
1352 } | |
1353 if (context->minimum_qos.ctrl_qos == PS_is_R97) { | |
1354 T_PS_qos_r97 *min_qos = &context->minimum_qos.qos.qos_r97; | |
1355 if (sm_qos->ctrl_qos == PS_is_R97) { | |
1356 /* | |
1357 less_than = sm_qos_compare_r97_lt_r97(&sm_qos->qos.qos_r97, min_qos); | |
1358 * Construct not used, as this function is called only during | |
1359 * MO modify procedures, which is a R99 feature. | |
1360 */ | |
1361 less_than = FALSE; | |
1362 } else { | |
1363 T_PS_qos_r99 tmp_qos; | |
1364 cl_qos_convert_r97_to_r99(min_qos, &tmp_qos); | |
1365 | |
1366 less_than = sm_qos_compare_r99_lt_r99(&sm_qos->qos.qos_r99, &tmp_qos); | |
1367 } | |
1368 } else if (context->minimum_qos.ctrl_qos == PS_is_R99) { | |
1369 T_PS_qos_r99 *min_qos = &context->minimum_qos.qos.qos_r99; | |
1370 if (sm_qos->ctrl_qos == PS_is_R97) { | |
1371 T_PS_qos_r99 tmp_qos; | |
1372 cl_qos_convert_r97_to_r99(&sm_qos->qos.qos_r97, &tmp_qos); | |
1373 | |
1374 less_than = sm_qos_compare_r99_lt_r99(&tmp_qos, min_qos); | |
1375 } else { | |
1376 less_than = sm_qos_compare_r99_lt_r99(&sm_qos->qos.qos_r99, min_qos); | |
1377 } | |
1378 } else { | |
1379 (void)TRACE_EVENT_P1("ERROR! Invalid union controller == %d in minimum QoS!", | |
1380 context->minimum_qos.ctrl_qos); | |
1381 } | |
1382 | |
1383 | |
1384 return !less_than; | |
1385 } | |
1386 | |
1387 /* | |
1388 +------------------------------------------------------------------------------ | |
1389 | Function : sm_qos_copy_from_sm | |
1390 +------------------------------------------------------------------------------ | |
1391 | Description : Copy QoS structure and union controller from context data to | |
1392 | another QoS structure (in a primitive etc). | |
1393 | | |
1394 | Parameters : dst - Destination QoS structure | |
1395 | src - Source QoS structure | |
1396 | dctrl - Destination union controller | |
1397 +------------------------------------------------------------------------------ | |
1398 */ | |
1399 void sm_qos_copy_from_sm(T_PS_qos *dst, T_SM_qos *src, T_PS_ctrl_qos *dctrl) | |
1400 { | |
1401 *dctrl = src->ctrl_qos; | |
1402 memcpy(dst, &src->qos, sizeof(T_PS_qos)); | |
1403 } | |
1404 | |
1405 /* | |
1406 +------------------------------------------------------------------------------ | |
1407 | Function : sm_qos_copy_to_sm | |
1408 +------------------------------------------------------------------------------ | |
1409 | Description : Copy QoS structure and union controller from e.g. a primitive | |
1410 | to context data. | |
1411 | | |
1412 | Parameters : dst - Destination QoS structure (in context data) | |
1413 | src - Source QoS structure | |
1414 | ctrl - Source union controller | |
1415 +------------------------------------------------------------------------------ | |
1416 */ | |
1417 void sm_qos_copy_to_sm(T_SM_qos *dst, T_PS_qos *src, T_PS_ctrl_qos ctrl) | |
1418 { | |
1419 dst->ctrl_qos = ctrl; | |
1420 memcpy(&dst->qos, src, sizeof(T_PS_qos)); | |
1421 } | |
1422 | |
1423 /* | |
1424 +------------------------------------------------------------------------------ | |
1425 | Function : sm_qos_is_requested_qos_present | |
1426 +------------------------------------------------------------------------------ | |
1427 | Description : Returns TRUE if requested QoS element is present. | |
1428 | | |
1429 | Parameters : context - Context data | |
1430 +------------------------------------------------------------------------------ | |
1431 */ | |
1432 BOOL sm_qos_is_requested_qos_present(struct T_SM_CONTEXT_DATA *context) | |
1433 { | |
1434 /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */ | |
1435 TRACE_ASSERT(context != NULL); | |
1436 | |
1437 return (context->requested_qos.ctrl_qos != PS_is_qos_not_present); | |
1438 } | |
1439 | |
1440 /* | |
1441 +------------------------------------------------------------------------------ | |
1442 | Function : sm_rank_del_contexts_based_on_tc | |
1443 +------------------------------------------------------------------------------ | |
1444 | Description : Ranks all contexts linked to a pdp address based on traffic | |
1445 | class and traffic handling priority. Locally deactivates all | |
1446 | but the best ranking context. Informs ACI about the deactivation. | |
1447 | Also sends a pdp context status request to GMM. | |
1448 | Reference 23.107 Annex C | |
1449 | | |
1450 | Parameters : None | |
1451 +------------------------------------------------------------------------------ | |
1452 */ | |
1453 #ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT | |
1454 | |
1455 U16 sm_rank_del_contexts_based_on_tc() | |
1456 { | |
1457 U8 nsapi = 0; | |
1458 U8 temp_ti = 0; | |
1459 U8 count = 0; | |
1460 U8 temp_nsapi = 0; | |
1461 U16 context_ti = 0; | |
1462 U16 linked_contexts = 0; | |
1463 U8 best_qos_rank = SM_HIGH_VALUE; /*Initialize with a high value*/ | |
1464 U16 nsapis_to_deactivate = 0; | |
1465 | |
1466 for (nsapi=(int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) | |
1467 { | |
1468 struct T_SM_CONTEXT_DATA *context; | |
1469 struct T_SM_CONTEXT_DATA *temp_context; | |
1470 | |
1471 context = sm_get_context_data_from_nsapi(nsapi); | |
1472 /* The context_control_state is checked to see if the context is already | |
1473 * getting deactivated | |
1474 */ | |
1475 if ( context != NULL && | |
1476 (context->context_control_state != SM_CONTEXT_DEACTIVATED) ) | |
1477 { | |
1478 if (sm_is_secondary(context)) | |
1479 { | |
1480 context_ti = context->linked_ti; | |
1481 } else { | |
1482 context_ti = context->ti; | |
1483 } | |
1484 linked_contexts = sm_add_nsapi_to_nsapi_set(nsapi, linked_contexts); | |
1485 count = 1; /*One context is already active*/ | |
1486 /*Rank this context. May be needed if linked contexts are active*/ | |
1487 context->qos_rank = sm_qos_rank_context(context->ti); | |
1488 if (context->qos_rank < best_qos_rank) { | |
1489 best_qos_rank = context->qos_rank; | |
1490 } | |
1491 } else { /*Go to the next nsapi*/ | |
1492 continue; | |
1493 } | |
1494 /* One context active. Check all the remaining active contexts */ | |
1495 for (temp_nsapi=nsapi; temp_nsapi < NAS_SIZE_NSAPI; temp_nsapi++) | |
1496 { | |
1497 temp_context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1498 if(temp_context != NULL && temp_context->context_control_state | |
1499 != SM_CONTEXT_DEACTIVATED) | |
1500 { | |
1501 if (sm_is_secondary(temp_context)) | |
1502 { | |
1503 temp_ti = temp_context->linked_ti; | |
1504 } else { | |
1505 temp_ti = temp_context->ti; | |
1506 } | |
1507 if ( (temp_nsapi != nsapi) && (temp_ti == context_ti) ) | |
1508 { | |
1509 linked_contexts = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1510 linked_contexts); | |
1511 count++; | |
1512 /*A second context active. Rank it. Pass the ti of the context*/ | |
1513 temp_context->qos_rank = sm_qos_rank_context(temp_context->ti); | |
1514 if (temp_context->qos_rank < best_qos_rank) { | |
1515 best_qos_rank = temp_context->qos_rank; | |
1516 } | |
1517 } | |
1518 } | |
1519 } | |
1520 | |
1521 if (count >=2 ) | |
1522 { | |
1523 for (temp_nsapi=(int)NAS_NSAPI_5; temp_nsapi<NAS_SIZE_NSAPI; temp_nsapi++) | |
1524 { | |
1525 struct T_SM_CONTEXT_DATA *context; | |
1526 if( (linked_contexts & (0x0001 << temp_nsapi)) != 0 ) | |
1527 { | |
1528 context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1529 if ( (context->qos_rank > best_qos_rank) && (context != NULL) | |
1530 && (context->context_control_state != SM_CONTEXT_DEACTIVATED) ) | |
1531 { | |
1532 (void)TRACE_EVENT_P1("Deactivating nsapi >>TC based << %d; ", temp_nsapi); | |
1533 /*deactivate the context*/ | |
1534 nsapis_to_deactivate = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1535 nsapis_to_deactivate); | |
1536 /* Make sure to clear the pending reactivation flag */ | |
1537 sm_set_context_pending_reactivation(context, FALSE); | |
1538 /* Order context deactivation */ | |
1539 sm_context_control(context, SM_I_CONTEXT_LOCAL_DEACTIVATE, | |
1540 (void *)TRUE); | |
1541 } | |
1542 } | |
1543 } | |
1544 } | |
1545 } | |
1546 | |
1547 return nsapis_to_deactivate; | |
1548 } | |
1549 #endif /*#ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT*/ | |
1550 | |
1551 | |
1552 /* | |
1553 +------------------------------------------------------------------------------ | |
1554 | Function : sm_qos_rank_context | |
1555 +------------------------------------------------------------------------------ | |
1556 | Description : Provides a rank for the context based on the tc and handling pri | |
1557 | Reference 23.107 Annex C | |
1558 | | |
1559 | Parameters : context ti | |
1560 +------------------------------------------------------------------------------ | |
1561 */ | |
1562 #ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT | |
1563 | |
1564 U8 sm_qos_rank_context(U16 ti) | |
1565 { | |
1566 struct T_SM_CONTEXT_DATA *context; | |
1567 T_PS_qos_r99 temp_qos; | |
1568 U8 qos_rank = 0; | |
1569 | |
1570 context = sm_get_context_data_from_ti(ti); | |
1571 | |
1572 if(context->accepted_qos.ctrl_qos == PS_is_R97) | |
1573 { /*R97 QoS. Convert to R99 QoS before ranking*/ | |
1574 (void)cl_qos_convert_r97_to_r99(&context->accepted_qos.qos.qos_r97, | |
1575 &temp_qos); | |
1576 } else | |
1577 { | |
1578 temp_qos = context->accepted_qos.qos.qos_r99; | |
1579 } | |
1580 | |
1581 switch(temp_qos.tc) | |
1582 { | |
1583 case PS_TC_INTER: | |
1584 switch(temp_qos.handling_pri) | |
1585 { | |
1586 case PS_HANDLING_PRI_1: | |
1587 qos_rank = 1; | |
1588 break; | |
1589 case PS_HANDLING_PRI_2: | |
1590 qos_rank = 4; | |
1591 break; | |
1592 case PS_HANDLING_PRI_3: | |
1593 qos_rank = 5; | |
1594 break; | |
1595 } | |
1596 break; | |
1597 case PS_TC_CONV: | |
1598 qos_rank = 2; | |
1599 break; | |
1600 case PS_TC_STREAM: | |
1601 qos_rank = 3; | |
1602 break; | |
1603 case PS_TC_BG: | |
1604 qos_rank = 6; | |
1605 break; | |
1606 default: | |
1607 qos_rank = 6; | |
1608 break; | |
1609 } | |
1610 return qos_rank; | |
1611 } | |
1612 #endif /*#ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT*/ | |
1613 | |
1614 /* | |
1615 +------------------------------------------------------------------------------ | |
1616 | Function : sm_retain_cntxt_wth_best_bitrate | |
1617 +------------------------------------------------------------------------------ | |
1618 | Description : Deactivates all the linked pdp contexts except the one with | |
1619 | highest max bit rate uplink or downlink. Informs ACI about the | |
1620 | deactivation. | |
1621 | Also sends a pdp context status request to GMM. | |
1622 | Reference 23.107 Annex C | |
1623 | | |
1624 | Parameters : None | |
1625 +------------------------------------------------------------------------------ | |
1626 */ | |
1627 #ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT | |
1628 | |
1629 U16 sm_retain_cntxt_wth_best_bitrate() | |
1630 { | |
1631 U8 nsapi = 0; | |
1632 U8 temp_nsapi = 0; | |
1633 U8 count = 0; | |
1634 U16 linked_contexts = 0; | |
1635 U16 best_max_bitrate = 0; | |
1636 U16 nsapis_to_deactivate = 0; | |
1637 U16 context_ti = 0; | |
1638 U16 temp_ti = 0; | |
1639 T_PS_qos_r99 temp_qos; | |
1640 | |
1641 | |
1642 for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) | |
1643 { | |
1644 struct T_SM_CONTEXT_DATA *context; | |
1645 struct T_SM_CONTEXT_DATA *temp_context; | |
1646 | |
1647 context = sm_get_context_data_from_nsapi(nsapi); | |
1648 if ( (context != NULL) && (context->context_control_state | |
1649 != SM_CONTEXT_DEACTIVATED) ) | |
1650 { | |
1651 if (sm_is_secondary(context)) | |
1652 { | |
1653 context_ti = context->linked_ti; | |
1654 } else { | |
1655 context_ti = context->ti; | |
1656 } | |
1657 linked_contexts = sm_add_nsapi_to_nsapi_set(nsapi, linked_contexts); | |
1658 count = 1; /*One context is already active*/ | |
1659 } else { /* Process the next nsapi */ | |
1660 continue; | |
1661 } | |
1662 | |
1663 for(temp_nsapi=nsapi; temp_nsapi < NAS_SIZE_NSAPI; temp_nsapi++) | |
1664 { | |
1665 temp_context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1666 if(temp_context != NULL && temp_context->context_control_state | |
1667 != SM_CONTEXT_DEACTIVATED) | |
1668 { | |
1669 if (sm_is_secondary(temp_context)) | |
1670 { | |
1671 temp_ti = temp_context->linked_ti; | |
1672 } else { | |
1673 temp_ti = temp_context->ti; | |
1674 } | |
1675 if ( (temp_nsapi != nsapi) && (temp_ti == context_ti) ) | |
1676 { | |
1677 linked_contexts = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1678 linked_contexts); | |
1679 count++; | |
1680 } | |
1681 } | |
1682 } | |
1683 | |
1684 if (count >=2) | |
1685 { /*Multiple contexts active for this ti. Find the best_max_bit rate.*/ | |
1686 (void)TRACE_EVENT( "Multiple contexts active: sm_retain_cntxt_wth_best_bitrate" ); | |
1687 for (temp_nsapi=(int)NAS_NSAPI_5; temp_nsapi < NAS_SIZE_NSAPI; temp_nsapi++) | |
1688 { | |
1689 if( (linked_contexts & (0x0001 << temp_nsapi)) != 0 ) | |
1690 { | |
1691 context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1692 if(context->accepted_qos.ctrl_qos == PS_is_R97) | |
1693 { /*R97 QoS. Convert to R99 QoS before ranking*/ | |
1694 (void)cl_qos_convert_r97_to_r99(&context->accepted_qos.qos.qos_r97, | |
1695 &temp_qos); | |
1696 } else { | |
1697 temp_qos = context->accepted_qos.qos.qos_r99; | |
1698 } | |
1699 if (temp_qos.max_rate_dl >= best_max_bitrate) | |
1700 { | |
1701 best_max_bitrate = temp_qos.max_rate_dl; | |
1702 } else if (temp_qos.max_rate_ul >= best_max_bitrate) { | |
1703 best_max_bitrate = temp_qos.max_rate_ul; | |
1704 } | |
1705 } | |
1706 } | |
1707 | |
1708 } | |
1709 | |
1710 if (count >=2) | |
1711 { | |
1712 for (temp_nsapi=(int)NAS_NSAPI_5; temp_nsapi < NAS_SIZE_NSAPI; temp_nsapi++) | |
1713 { | |
1714 if( (linked_contexts & (0x0001 << temp_nsapi)) != 0 ) | |
1715 { | |
1716 context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1717 if(context->accepted_qos.ctrl_qos == PS_is_R97) | |
1718 { /*R97 QoS. Convert to R99 QoS before ranking*/ | |
1719 (void)cl_qos_convert_r97_to_r99(&context->accepted_qos.qos.qos_r97, | |
1720 &temp_qos); | |
1721 } else { | |
1722 temp_qos = context->accepted_qos.qos.qos_r99; | |
1723 } | |
1724 if ( (temp_qos.max_rate_dl == best_max_bitrate) || | |
1725 (temp_qos.max_rate_ul == best_max_bitrate) ) | |
1726 { | |
1727 /* Don't do anything */ | |
1728 } | |
1729 else /* Deactivate the context */ | |
1730 { | |
1731 (void)TRACE_EVENT_P1("Deactivating nsapi << bit rate based >> %d; ", temp_nsapi); | |
1732 /*Deactivate the context*/ | |
1733 nsapis_to_deactivate = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1734 nsapis_to_deactivate); | |
1735 /* Make sure to clear the pending reactivation flag */ | |
1736 sm_set_context_pending_reactivation(context, FALSE); | |
1737 /* Order context deactivation */ | |
1738 sm_context_control(context, SM_I_CONTEXT_LOCAL_DEACTIVATE, | |
1739 (void *)TRUE); | |
1740 } | |
1741 } | |
1742 } | |
1743 } | |
1744 | |
1745 } | |
1746 return nsapis_to_deactivate; | |
1747 } | |
1748 | |
1749 #endif /*#ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT*/ | |
1750 | |
1751 /* | |
1752 +------------------------------------------------------------------------------ | |
1753 | Function : sm_retain_cntxt_with_least_nsapi | |
1754 +------------------------------------------------------------------------------ | |
1755 | Description : Deactivates all the linked pdp contexts except the one with | |
1756 | least nsapi value. Informs ACI about the deactivation. | |
1757 | Also sends a pdp context status request to GMM. | |
1758 | Reference 23.107 Annex C | |
1759 | | |
1760 | Parameters : None | |
1761 +------------------------------------------------------------------------------ | |
1762 */ | |
1763 #ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT | |
1764 | |
1765 U16 sm_retain_cntxt_with_least_nsapi() | |
1766 { | |
1767 struct T_SM_CONTEXT_DATA *context; | |
1768 struct T_SM_CONTEXT_DATA *temp_context; | |
1769 U8 nsapi = 0; | |
1770 U8 temp_nsapi = 0; | |
1771 U16 linked_contexts = 0; | |
1772 U16 nsapis_to_deactivate = 0; | |
1773 U16 best_max_bitrate = 0; | |
1774 U8 min_nsapi = SM_HIGH_VALUE; /*Initialize to a high value. Here 255*/ | |
1775 U8 count = 0; | |
1776 U16 context_ti,temp_ti = 0; | |
1777 | |
1778 | |
1779 for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) | |
1780 { | |
1781 context = sm_get_context_data_from_nsapi(nsapi); | |
1782 if ( (context != NULL) && (context->context_control_state != | |
1783 SM_CONTEXT_DEACTIVATED) ) | |
1784 { | |
1785 if (sm_is_secondary(context)) | |
1786 { | |
1787 context_ti = context->linked_ti; | |
1788 } else { | |
1789 context_ti = context->ti; | |
1790 } | |
1791 linked_contexts = sm_add_nsapi_to_nsapi_set(nsapi, linked_contexts); | |
1792 count = 1; /*One context is already active*/ | |
1793 } else { /*Go to the next nsapi*/ | |
1794 continue; | |
1795 } | |
1796 | |
1797 /* Check all the remaining active contexts */ | |
1798 for (temp_nsapi=nsapi; temp_nsapi < NAS_SIZE_NSAPI; temp_nsapi++) | |
1799 { | |
1800 temp_context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1801 if(temp_context != NULL && temp_context->context_control_state | |
1802 != SM_CONTEXT_DEACTIVATED) | |
1803 { | |
1804 if (sm_is_secondary(temp_context)) | |
1805 { | |
1806 temp_ti = temp_context->linked_ti; | |
1807 } else { | |
1808 temp_ti = temp_context->ti; | |
1809 } | |
1810 if ( (temp_nsapi != nsapi) && (temp_ti == context_ti) ) | |
1811 { | |
1812 linked_contexts = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1813 linked_contexts); | |
1814 count++; | |
1815 } | |
1816 } | |
1817 } | |
1818 | |
1819 | |
1820 if (count >= 2) | |
1821 { /*Multiple contexts active for this ti. Try deactivating.*/ | |
1822 (void)TRACE_EVENT( "Multiple contexts active: sm_retain_cntxt_with_least_nsapi" ); | |
1823 for (temp_nsapi=(int)NAS_NSAPI_5; temp_nsapi<NAS_SIZE_NSAPI; temp_nsapi++) | |
1824 { | |
1825 if( (linked_contexts & (0x0001 << temp_nsapi)) != 0 ) | |
1826 { | |
1827 temp_context = sm_get_context_data_from_nsapi(temp_nsapi); | |
1828 if ((min_nsapi == SM_HIGH_VALUE) && (temp_context != NULL) && | |
1829 (temp_context->context_control_state != SM_CONTEXT_DEACTIVATED) ) | |
1830 { | |
1831 min_nsapi = temp_nsapi; | |
1832 } else | |
1833 { | |
1834 (void)TRACE_EVENT_P1("Deactivating nsapi >>nsapi based << %d; ", temp_nsapi); | |
1835 /*Deactivate the context*/ | |
1836 nsapis_to_deactivate = sm_add_nsapi_to_nsapi_set(temp_nsapi, | |
1837 nsapis_to_deactivate); | |
1838 /* Make sure to clear the pending reactivation flag */ | |
1839 sm_set_context_pending_reactivation(temp_context, FALSE); | |
1840 /* Order context deactivation */ | |
1841 sm_context_control(temp_context, SM_I_CONTEXT_LOCAL_DEACTIVATE, | |
1842 (void *)TRUE); | |
1843 } | |
1844 } | |
1845 } | |
1846 } | |
1847 } | |
1848 return nsapis_to_deactivate; | |
1849 } | |
1850 | |
1851 #endif /*#ifdef TI_PS_OP_SM_RETAIN_BEST_CONTEXT*/ | |
1852 |