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