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