FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/cl/clqos.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/cl/clqos.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,464 @@ +/*----------------------------------------------------------------------------- +| Project : 3G UMTS PS +| Module : CL ++------------------------------------------------------------------------------ +| Copyright 2003 Texas Instruments. +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments . +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments. ++------------------------------------------------------------------------------ +| Purpose: QoS handling functions. +| For design details, see: +| 8010.149 CL SAP ++----------------------------------------------------------------------------*/ + +#ifndef CLQOS_C +#define CLQOS_C +#endif + +#ifndef ENTITY_CL +#define ENTITY_CL +#endif +#define ENTITY_CLT + +/*==== INCLUDES =============================================================*/ + +#include "typedefs.h" /* to get TI data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "gsm.h" /* to get a lot of macros */ +#include "message.h" /* to get the message definitions for sm */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "p_cl.val" /* to get the type of sgsn_rel*/ +#include "p_8010_152_ps_include.h" /*to get T_PS_qos_rXX*/ +#include "cl_inline.h" + + +typedef U8 T_CL_result; /*I really don't like this ! Can we do something in cl.sap ?*/ + +/*==== CONST ================================================================*/ + +/* + * Conversion table for 1/n in T_ratio. + * Contains 1/n * 1E9 entries used for scaling. + */ +static const U32 cl_qos_ratio_table[10] = { + 0UL, + 1000000000UL, /* 1E9 / 1 */ + 500000000UL, /* 1E9 / 2 */ + 333333333UL, /* 1E9 / 3 */ + 250000000UL, /* 1E9 / 4 */ + 200000000UL, /* 1E9 / 5 */ + 166666667UL, /* 1E9 / 6 */ + 142857143UL, /* 1E9 / 7 */ + 125000000UL, /* 1E9 / 8 */ + 111111111UL /* 1E9 / 9 */ +}; + +/*==== LOCAL VARS ===========================================================*/ + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +/*----------------------------------------------------------------------------- +| Function : cl_qos_ratio_to_U32 ++------------------------------------------------------------------------------ +| Description : Conversion function: T_ratio to integer +| +| Parameters : T_ratio +| +| Return : ratio as integer ++----------------------------------------------------------------------------*/ +static U32 cl_qos_ratio_to_U32(U8 ratio_mant, U8 ratio_exp) +{ + U32 value; + int count; + + /* Error checks */ + if (ratio_exp > (U8)9) + { + /*TRACE_ERROR( "QoS ratio exponent parameter out of bounds!" );*/ + return 0; + } + else + { + if (ratio_mant > (U8)9) + { + /*TRACE_ERROR( "QoS ratio exponent parameter out of bounds!" );*/ + return 0; + } + else + { + if (ratio_exp == (U8)9 && ratio_mant < (U8)5) + { + /*TRACE_ERROR( "QoS ratio parameter exceeds data type range!" );*/ + return 0; + } + } + } + + for (count = 9-(int)ratio_exp, value = 1UL; count > 0; count--) + { + value *= 10; + } + /* Get real value by rounding 1/x and dividing by 10^(9-ratio_exp) */ + value = (cl_qos_ratio_table[(U16)ratio_mant] + (value >> 1)) / value; + + return value; +} + +/*----------------------------------------------------------------------------- +| Function : cl_qos_r99_to_delay ++------------------------------------------------------------------------------ +| Description : Given an input R99 QoS, return the corresponding R97 delay +| parameter +| +| Parameters : R99 Qos +| +| Return : Delay ++----------------------------------------------------------------------------*/ +static T_PS_delay cl_qos_r99_to_delay(T_PS_qos_r99 *src_qos_r99) +{ + T_PS_delay delay; + + /* Traffic class / handling priority */ + switch ((T_PS_tc)src_qos_r99->tc) + { + case PS_TC_SUB: /* 0 - Subscribed */ + delay = PS_DELAY_SUB; + break; + case PS_TC_CONV: /* 1 - Conversational */ + delay = PS_DELAY_1; + break; + case PS_TC_STREAM: /* 2 - Streaming */ + delay = PS_DELAY_1; + break; + case PS_TC_INTER: /* 3 - Interactive */ + switch (src_qos_r99->handling_pri) + { + case PS_HANDLING_PRI_1: + delay = PS_DELAY_1; + break; + case PS_HANDLING_PRI_2: + delay = PS_DELAY_2; + break; + case PS_HANDLING_PRI_3: + default: /* For safety */ + delay = PS_DELAY_3; + break; + } /* switch */ + break; + case PS_TC_BG: /* 4 - Background */ + delay = PS_DELAY_4; + break; + default: /* 5, 6, 7 or other garbage */ + delay = PS_DELAY_SUB; + break; + } /* switch */ + + return delay; +} /* cl_qos_r99_to_delay */ + +/*----------------------------------------------------------------------------- +| Function : cl_qos_r99_to_relclass ++------------------------------------------------------------------------------ +| Description : Given an input R99 QoS, return the corresponding R97 relclass +| parameter +| +| Parameters : R99 Qos +| +| Return : Reliability class ++----------------------------------------------------------------------------*/ +static T_PS_relclass cl_qos_r99_to_relclass(T_PS_qos_r99 *src_qos_r99) +{ + U32 sdu_err; + T_PS_relclass relclass; + + /* First, convert SDU error ratio to integral number */ + sdu_err = cl_qos_ratio_to_U32(src_qos_r99->sdu_err_ratio.ratio_mant, + src_qos_r99->sdu_err_ratio.ratio_exp); + + if (sdu_err == 0UL) + { /* SDU err ratio == subscribed value */ + relclass = PS_RELCLASS_SUB; /* 0 */ + } + else + { + if (sdu_err >= 100000UL) + { /* SDU err ratio <= 1E-5 */ + relclass = PS_LLC_RLC_PROT; /* 2 */ + } + else + { + if (sdu_err >= 2000UL) + { /* 1E-5 < SDU err ratio <= 5E-4 */ + relclass = PS_RLC_PROT; /* 3 */ + } + else + { /* SDU err ratio > 5E-4 */ + if (src_qos_r99->ber.ratio_exp > (U8)4 || + (src_qos_r99->ber.ratio_exp == (U8)4 && src_qos_r99->ber.ratio_mant >= (U8)2)) + { + /* BER <= 2E-4 */ + relclass = PS_PROT; /* 4 */ + } + else + { /* BER > 2E-4 */ + relclass = PS_NO_REL; /* 5 */ + } + } + } + } /* if (sdu_err ...) */ + + return relclass; +} + +/*==== PUBLIC FUNCTIONS =====================================================*/ + +/*----------------------------------------------------------------------------- +| Function : cl_qos_convert_r99_to_r97_req ++------------------------------------------------------------------------------ +| Description : Function for converting a R99 QoS parameter set to a R97/R98 +| ditto. Conversion rules according to [3G 23.107, sec 9] +| +| Parameters : Originating R99 QoS parameter struct +| Destination R97 QoS parameter struct (overwritten in this function) +| +| Return : Conversion result and Destination R97 QoS parameter struct. ++----------------------------------------------------------------------------*/ +T_CL_result cl_qos_convert_r99_to_r97(T_PS_qos_r99 *src_qos_r99, + T_PS_qos_r97 *dst_qos_r97) +{ + T_CL_result success = (T_CL_result)TRUE; + U16 count, max_rate; + + dst_qos_r97->delay = (U8)cl_qos_r99_to_delay(src_qos_r99); + + /* + * SDU error ratio / Residual bit error ratio + */ + dst_qos_r97->relclass = (U8)cl_qos_r99_to_relclass(src_qos_r99); + + /* + * Maximum bit-rate + * + * In case max uplink and downlink data rates differ, [3G 23.107] + * says to map according to max(R99_uplink, R99_downlink), + * i.e. the higher of the two. + */ + max_rate = (src_qos_r99->max_rate_ul > src_qos_r99->max_rate_dl ? + src_qos_r99->max_rate_ul : src_qos_r99->max_rate_dl); + + if (max_rate == (U16)PS_MAX_BR_UL_SUB) + { /* Subscribed */ + dst_qos_r97->peak = (U8)PS_PEAK_SUB; + } + else + { /* ! Subscribed */ + /* Perform pseudo log2(bit-rate). Really, we are finding the highest set + * bit to use in our comparison rather than making a *huge* + * if-[else if]*-else clause. + * Fixed ceiling to 2048 (count < 12) => max_rate <= 2^11 */ + for (count = (U16)4; ((max_rate >> count) != 0) && count < (U16)12; count++); + + /* The quick / code optimal way: + * dst_qos_r97->peak = count - 3; */ + + switch (count) + { + case 4: dst_qos_r97->peak = (U8)PS_PEAK_1K; break; + case 5: dst_qos_r97->peak = (U8)PS_PEAK_2K; break; + case 6: dst_qos_r97->peak = (U8)PS_PEAK_4K; break; + case 7: dst_qos_r97->peak = (U8)PS_PEAK_8K; break; + case 8: dst_qos_r97->peak = (U8)PS_PEAK_16K; break; + case 9: dst_qos_r97->peak = (U8)PS_PEAK_32K; break; + case 10: dst_qos_r97->peak = (U8)PS_PEAK_64K; break; + case 11: dst_qos_r97->peak = (U8)PS_PEAK_128K; break; + case 12: dst_qos_r97->peak = (U8)PS_PEAK_256K; break; + } /* switch */ + } /* if - Subscribed */ + + /* R97 peak throughput class is fixed to 31 (best effort) */ + dst_qos_r97->mean = (U8)PS_MEAN_BEST; + dst_qos_r97->preced = (U8)PS_PRECED_SUB; + + return success; +} + +/*----------------------------------------------------------------------------- +| Function : cl_qos_convert_r97_to_r99_req ++------------------------------------------------------------------------------ +| Description : Function for converting a R97/R98 QoS parameter set to a R99 +| ditto. Conversion rules according to [3G 23.107, sec 9] +| +| Parameters : Originating R97 QoS parameter struct +| Destination R99 QoS parameter struct (overwritten in this function) +| +| Return : Conversion result and Destination R99 QoS parameter struct. ++----------------------------------------------------------------------------*/ +T_CL_result cl_qos_convert_r97_to_r99(T_PS_qos_r97 *src_qos_r97, + T_PS_qos_r99 *dst_qos_r99) +{ + T_CL_result success = (T_CL_result)TRUE; + + /* Delay parameter */ + switch ((T_PS_delay)src_qos_r97->delay) + { + case PS_DELAY_SUB: /* 0 */ + dst_qos_r99->tc = (U8)PS_TC_SUB; + dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_SUB; + break; + case PS_DELAY_1: /* 1 */ + dst_qos_r99->tc = (U8)PS_TC_INTER; + dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_1; + break; + case PS_DELAY_2: /* 2 */ + dst_qos_r99->tc = (U8)PS_TC_INTER; + dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_2; + break; + case PS_DELAY_3: /* 3 */ + dst_qos_r99->tc = (U8)PS_TC_INTER; + dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_3; + break; + case PS_DELAY_4: /* 4 */ + dst_qos_r99->tc = (U8)PS_TC_BG; + dst_qos_r99->handling_pri = (U8)PS_HANDLING_PRI_SUB; + break; + default: /* 5 - 7 or other garbage */ + /* Error handling? */ + success = (T_CL_result)FALSE; + break; + } /* switch */ + + /* Reliability class */ + switch ((T_PS_relclass)src_qos_r97->relclass) + { + case PS_RELCLASS_SUB: /* 0 - Subscribed */ + dst_qos_r99->sdu_err_ratio.ratio_mant = dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)0; + dst_qos_r99->ber.ratio_mant = dst_qos_r99->ber.ratio_exp = (U8)0; + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_SUB; + break; + case PS_GTP_LLC_RLC_PROT: /* 1 - Acknowledged GTP, LLC, and RLC */ + dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1; + dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)6; /* SDU error ratio = 1E-6 */ + dst_qos_r99->ber.ratio_mant = (U8)1; + dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */ + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO; + break; + case PS_LLC_RLC_PROT: /* 2 - Unacknowledged GTP; Acknowledged LLC and RLC */ + dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1; + dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)6; /* SDU error ratio = 1E-6 */ + dst_qos_r99->ber.ratio_mant = (U8)1; + dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */ + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO; + break; + case PS_RLC_PROT: /* 3 - Unacknowledged GTP and LLC; Acknowledged RLC */ + dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1; + dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)4; /* SDU error ratio = 1E-4 */ + dst_qos_r99->ber.ratio_mant = (U8)1; + dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */ + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO; + break; + case PS_PROT: /* 4 - Unacknowledged GTP, LLC, and RLC */ + dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1; + dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)3; /* SDU error ratio = 1E-3 */ + dst_qos_r99->ber.ratio_mant = (U8)1; + dst_qos_r99->ber.ratio_exp = (U8)5; /* Residual BER = 1E-5 */ + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_NO; + break; + case PS_NO_REL: /* 5 - Unacknowledged GTP, LLC, and RLC (Unprotected) */ + dst_qos_r99->sdu_err_ratio.ratio_mant = (U8)1; + dst_qos_r99->sdu_err_ratio.ratio_exp = (U8)3; /* SDU error ratio = 1E-3 */ + dst_qos_r99->ber.ratio_mant = (U8)4; + dst_qos_r99->ber.ratio_exp = (U8)3; /* Residual BER = 4E-3 */ + dst_qos_r99->del_err_sdu = (U8)PS_DEL_ERR_YES; + break; + default: /* 6, 7 or other garbage */ + /* Error handling? */ + success = (T_CL_result)FALSE; + break; + } /* switch */ + + /* Peak throughput parameter */ + /* NOTE: Could be optimized heavily into the following: + * dst_qos_r99->max_br_dl = dst_qos_r99->max_br_ul = (peak == 0 ? 0 : 4 << peak) + */ + + switch ((T_PS_peak)src_qos_r97->peak) + { + case PS_PEAK_SUB: /* 0 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)PS_MAX_BR_UL_SUB; + break; + case PS_PEAK_1K: /* 1 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)8; + break; + case PS_PEAK_2K: /* 2 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)16; + break; + case PS_PEAK_4K: /* 3 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)32; + break; + case PS_PEAK_8K: /* 4 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)64; + break; + case PS_PEAK_16K: /* 5 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)128; + break; + case PS_PEAK_32K: /* 6 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)256; + break; + case PS_PEAK_64K: /* 7 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)512; + break; + case PS_PEAK_128K: /* 8 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)1024; + break; + case PS_PEAK_256K: /* 9 */ + dst_qos_r99->max_rate_dl = dst_qos_r99->max_rate_ul = (U16)2048; + break; + default: + /* Handling? */ + success = (T_CL_result)FALSE; + break; + } /* switch */ + + /* R99 max SDU size is fixed to 1500 */ + dst_qos_r99->max_sdu = (U16)1500; + + /* Remaining R99 fields are not specified. We fill them in with subscribed */ + dst_qos_r99->order = (U8)PS_ORDER_SUB; + dst_qos_r99->xfer_delay = (U16)PS_XFER_DELAY_SUB; + dst_qos_r99->guar_br_ul = (U16)PS_GUAR_BR_UL_SUB; + dst_qos_r99->guar_br_dl = (U16)PS_GUAR_BR_DL_SUB; + + return success; +} + +/*----------------------------------------------------------------------------- +| Function : cl_qos_use_ack_mode_llc_req ++------------------------------------------------------------------------------ +| Description : Query function: Given input QoS, should NSAPI use acknowledged +| LLC mode? +| +| Parameters : Originating R99 QoS parameter struct +| +| Return : LLC mode ++----------------------------------------------------------------------------*/ +T_PS_llc_mode cl_qos_use_ack_mode_llc(T_PS_qos_r99 *src_qos_r99) +{ + T_PS_relclass relclass; + T_PS_llc_mode ret_val = PS_LLC_UNACKNOWLEDGED; + + relclass = cl_qos_r99_to_relclass(src_qos_r99); + + if (relclass == PS_GTP_LLC_RLC_PROT || relclass == PS_LLC_RLC_PROT) + { + ret_val = PS_LLC_ACKNOWLEDGED; + } + + return ret_val; +}