diff options
-rw-r--r-- | src/bts.h | 4 | ||||
-rw-r--r-- | src/encoding.cpp | 9 | ||||
-rw-r--r-- | src/pcu_main.cpp | 4 | ||||
-rw-r--r-- | src/pcu_vty.c | 24 | ||||
-rw-r--r-- | src/pcu_vty_functions.cpp | 3 | ||||
-rw-r--r-- | src/tbf.cpp | 18 | ||||
-rw-r--r-- | tests/tbf/TbfTest.cpp | 56 | ||||
-rw-r--r-- | tests/tbf/TbfTest.err | 75 | ||||
-rw-r--r-- | tests/tbf/TbfTest.ok | 2 |
9 files changed, 189 insertions, 6 deletions
@@ -188,8 +188,8 @@ struct gprs_rlcmac_bts { uint8_t cs_adj_lower_limit; struct {int16_t low; int16_t high;} cs_lqual_ranges[4]; uint16_t cs_downgrade_threshold; /* downgrade if less packets left (DL) */ - uint16_t egprs_ws_base; - uint16_t egprs_ws_lin; + uint16_t ws_base; + uint16_t ws_pdch; /* increase WS by this value per PDCH */ /* State for dynamic algorithm selection */ int multislot_disabled; diff --git a/src/encoding.cpp b/src/encoding.cpp index 9def2831..a26a5db4 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -208,13 +208,14 @@ void Encoding::write_packet_uplink_assignment( } } else { /* EPGRS */ + unsigned int ws_enc = (tbf->m_window.ws() - 64) / 32; bitvec_write_field(dest, wp,0x1,1); // Message escape bitvec_write_field(dest, wp,0x0,2); // EGPRS message contents bitvec_write_field(dest, wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI bitvec_write_field(dest, wp,0x0,1); // No COMPACT reduced MA bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE bitvec_write_field(dest, wp,0x0,1); // No RESEGMENT - bitvec_write_field(dest, wp,0x0,5); // EGPRS Window Size = 64 + bitvec_write_field(dest, wp,ws_enc,5); // EGPRS Window Size bitvec_write_field(dest, wp,0x0,1); // No Access Technologies Request bitvec_write_field(dest, wp,0x0,1); // No ARAC RETRANSMISSION REQUEST bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING @@ -282,6 +283,7 @@ void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, PDA_AdditionsR99_t *pda_r99; uint8_t tn; + unsigned int ws_enc; block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header block->RRBP = 0x0; // N+13 @@ -348,10 +350,13 @@ void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off return; } + + ws_enc = (tbf->window()->ws() - 64) / 32; + block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x1; // AdditionsR99 = on pda_r99 = &block->u.Packet_Downlink_Assignment.AdditionsR99; pda_r99->Exist_EGPRS_Params = 1; - pda_r99->EGPRS_WindowSize = 0; /* 64, see TS 44.060, table 12.5.2.1 */ + pda_r99->EGPRS_WindowSize = ws_enc; /* see TS 44.060, table 12.5.2.1 */ pda_r99->LINK_QUALITY_MEASUREMENT_MODE = 0x0; /* no meas, see TS 44.060, table 11.2.7.2 */ pda_r99->Exist_BEP_PERIOD2 = 0; /* No extra EGPRS BEP PERIOD */ pda_r99->Exist_Packet_Extended_Timing_Advance = 0; diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp index 39de0555..51a4eeec 100644 --- a/src/pcu_main.cpp +++ b/src/pcu_main.cpp @@ -193,6 +193,10 @@ int main(int argc, char *argv[]) bts->cs_lqual_ranges[3].high = 256; bts->cs_downgrade_threshold = 200; + /* TODO: increase them when CRBB decoding is implemented */ + bts->ws_base = 64; + bts->ws_pdch = 0; + bts->llc_codel_interval_msec = LLC_CODEL_USE_DEFAULT; bts->dl_tbf_idle_msec = 2000; bts->llc_idle_ack_csec = 10; diff --git a/src/pcu_vty.c b/src/pcu_vty.c index 97be4c72..b5ee1b55 100644 --- a/src/pcu_vty.c +++ b/src/pcu_vty.c @@ -118,6 +118,9 @@ static int config_write_pcu(struct vty *vty) bts->max_mcs_ul, VTY_NEWLINE); } + vty_out(vty, " window-size %d %d%s", bts->ws_base, bts->ws_pdch, + VTY_NEWLINE); + if (bts->force_llc_lifetime == 0xffff) vty_out(vty, " queue lifetime infinite%s", VTY_NEWLINE); else if (bts->force_llc_lifetime) @@ -437,6 +440,26 @@ DEFUN(cfg_pcu_no_mcs_max, return CMD_SUCCESS; } +DEFUN(cfg_pcu_window_size, + cfg_pcu_window_size_cmd, + "window-size <0-1024> [<0-256>]", + "Window size configuration (b + N_PDCH * f)\n" + "Base value (b)\n" + "Factor for number of PDCH (f)") +{ + struct gprs_rlcmac_bts *bts = bts_main_data(); + uint16_t b = atoi(argv[0]); + + bts->ws_base = b; + if (argc > 1) { + uint16_t f = atoi(argv[1]); + bts->ws_pdch = f; + } + + return CMD_SUCCESS; +} + + #define QUEUE_STR "Packet queue options\n" #define LIFETIME_STR "Set lifetime limit of LLC frame in centi-seconds " \ "(overrides the value given by SGSN)\n" @@ -892,6 +915,7 @@ int pcu_vty_init(const struct log_info *cat) install_element(PCU_NODE, &cfg_pcu_cs_lqual_ranges_cmd); install_element(PCU_NODE, &cfg_pcu_mcs_max_cmd); install_element(PCU_NODE, &cfg_pcu_no_mcs_max_cmd); + install_element(PCU_NODE, &cfg_pcu_window_size_cmd); install_element(PCU_NODE, &cfg_pcu_queue_lifetime_cmd); install_element(PCU_NODE, &cfg_pcu_queue_lifetime_inf_cmd); install_element(PCU_NODE, &cfg_pcu_no_queue_lifetime_cmd); diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp index 2f7cb02a..66994ded 100644 --- a/src/pcu_vty_functions.cpp +++ b/src/pcu_vty_functions.cpp @@ -56,7 +56,8 @@ static void tbf_print_vty_info(struct vty *vty, gprs_rlcmac_tbf *tbf) if (tbf->pdch[i]) vty_out(vty, "%d ", i); } - vty_out(vty, " CS=%s%s%s", tbf->current_cs().name(), + vty_out(vty, " CS=%s WS=%d%s%s", + tbf->current_cs().name(), tbf->window()->ws(), VTY_NEWLINE, VTY_NEWLINE); } diff --git a/src/tbf.cpp b/src/tbf.cpp index 9f19c9b7..c852d665 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -28,6 +28,7 @@ #include <gprs_bssgp_pcu.h> #include <gprs_ms.h> #include <decoding.h> +#include <pcu_utils.h> extern "C" { #include <osmocom/core/msgb.h> @@ -634,6 +635,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, if (egprs_ms_class > 0 && bts->egprs_enabled) { tbf->enable_egprs(); tbf->m_window.set_sns(RLC_EGPRS_SNS); + /* TODO: Allow bigger UL windows when CRBB encoding is supported */ tbf->m_window.set_ws(RLC_EGPRS_MIN_WS); setup_egprs_mode(bts, ms); LOGP(DRLCMAC, LOGL_INFO, "Enabled EGPRS for %s, mode %s\n", @@ -714,7 +716,6 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, if (egprs_ms_class > 0 && bts->egprs_enabled) { tbf->enable_egprs(); tbf->m_window.set_sns(RLC_EGPRS_SNS); - tbf->m_window.set_ws(RLC_EGPRS_MIN_WS); setup_egprs_mode(bts, ms); LOGP(DRLCMAC, LOGL_INFO, "Enabled EGPRS for %s, mode %s\n", tbf->name(), GprsCodingScheme::modeName(ms->mode())); @@ -727,6 +728,21 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, return NULL; } + if (tbf->is_egprs_enabled()) { + unsigned int num_pdch = pcu_bitcount(tbf->dl_slots()); + unsigned int ws = bts->ws_base + num_pdch * bts->ws_pdch; + ws = (ws / 32) * 32; + ws = OSMO_MAX(64, ws); + if (num_pdch == 1) + ws = OSMO_MIN(192, ws); + else + ws = OSMO_MIN(128 * num_pdch, ws); + + LOGP(DRLCMAC, LOGL_INFO, "%s: Setting EGPRS window size to %d\n", + tbf->name(), ws); + tbf->m_window.set_ws(ws); + } + llist_add(&tbf->list(), &bts->bts->dl_tbfs()); tbf->bts->tbf_dl_created(); diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 895ba8e5..c868ca2d 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -1105,6 +1105,61 @@ static void test_tbf_gprs_egprs() gprs_bssgp_destroy(); } +static void test_tbf_ws() +{ + BTS the_bts; + gprs_rlcmac_bts *bts; + uint8_t ts_no = 4; + uint8_t ms_class = 12; + gprs_rlcmac_dl_tbf *dl_tbf; + + printf("=== start %s ===\n", __func__); + + bts = the_bts.bts_data(); + setup_bts(&the_bts, ts_no); + + bts->ws_base = 128; + bts->ws_pdch = 64; + bts->alloc_algorithm = alloc_algorithm_b; + bts->trx[0].pdch[2].enable(); + bts->trx[0].pdch[3].enable(); + bts->trx[0].pdch[4].enable(); + bts->trx[0].pdch[5].enable(); + + gprs_bssgp_create_and_connect(bts, 33001, 0, 33001, + 1234, 1234, 1234, 1, 1, 0, 0, 0); + + /* Does no support EGPRS */ + dl_tbf = tbf_alloc_dl_tbf(bts, NULL, 0, ms_class, 0, 0); + OSMO_ASSERT(dl_tbf != NULL); + fprintf(stderr, "DL TBF slots: 0x%02x, N: %d, WS: %d\n", + dl_tbf->dl_slots(), + pcu_bitcount(dl_tbf->dl_slots()), + dl_tbf->window()->ws()); + OSMO_ASSERT(pcu_bitcount(dl_tbf->dl_slots()) == 4); + OSMO_ASSERT(dl_tbf->window()->ws() == 64); + tbf_free(dl_tbf); + + /* EGPRS-only */ + bts->egprs_enabled = 1; + + /* Does support EGPRS */ + dl_tbf = tbf_alloc_dl_tbf(bts, NULL, 0, ms_class, ms_class, 0); + + OSMO_ASSERT(dl_tbf != NULL); + fprintf(stderr, "DL TBF slots: 0x%02x, N: %d, WS: %d\n", + dl_tbf->dl_slots(), + pcu_bitcount(dl_tbf->dl_slots()), + dl_tbf->window()->ws()); + OSMO_ASSERT(pcu_bitcount(dl_tbf->dl_slots()) == 4); + OSMO_ASSERT(dl_tbf->window()->ws() == 128 + 4 * 64); + tbf_free(dl_tbf); + + printf("=== end %s ===\n", __func__); + + gprs_bssgp_destroy(); +} + static const struct log_info_cat default_categories[] = { {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0}, {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1}, @@ -1163,6 +1218,7 @@ int main(int argc, char **argv) test_tbf_dl_flow_and_rach_single_phase(); test_tbf_dl_reuse(); test_tbf_gprs_egprs(); + test_tbf_ws(); if (getenv("TALLOC_REPORT_FULL")) talloc_report_full(tall_pcu_ctx, stderr); diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 0ca4b829..a93d959b 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -3041,3 +3041,78 @@ msg block (BSN 10, CS-1): 0f 03 14 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654448 block=1 data=08 03 14 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29 Not accepting non-EGPRS phone in EGPRS-only mode No PDCH resource +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=12/0 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 12 +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +Slot Allocation (Algorithm B) for class 12 +- Rx=4 Tx=4 Sum Rx+Tx=5 Tta=2 Ttb=1 Tra=2 Trb=1 Type=1 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Possible DL/UL slots: (TS=0)"..CCCC.."(TS=7) +- Selected DL slots: (TS=0)"..DDDD.."(TS=7) +Using 4 slots for DL +- Reserved DL/UL slots: (TS=0)"..DDCD.."(TS=7) +- Assigning DL TS 2 +PDCH(TS 2, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 3 +PDCH(TS 3, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 4 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 5 +PDCH(TS 5, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 3c +DL TBF slots: 0x3c, N: 4, WS: 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) free +PDCH(TS 2, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 3, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) +Destroying MS object, TLLI = 0x00000000 +********** TBF ends here ********** +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=12/12 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 12 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 12 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +Slot Allocation (Algorithm B) for class 12 +- Rx=4 Tx=4 Sum Rx+Tx=5 Tta=2 Ttb=1 Tra=2 Trb=1 Type=1 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Possible DL/UL slots: (TS=0)"..CCCC.."(TS=7) +- Selected DL slots: (TS=0)"..DDDD.."(TS=7) +Using 4 slots for DL +- Reserved DL/UL slots: (TS=0)"..DDCD.."(TS=7) +- Assigning DL TS 2 +PDCH(TS 2, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 3 +PDCH(TS 3, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 4 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Assigning DL TS 5 +PDCH(TS 5, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 3c +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 384 +DL TBF slots: 0x3c, N: 4, WS: 384 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) free +PDCH(TS 2, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 3, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Destroying MS object, TLLI = 0x00000000 +********** TBF ends here ********** diff --git a/tests/tbf/TbfTest.ok b/tests/tbf/TbfTest.ok index c4bc8705..c6c4aea2 100644 --- a/tests/tbf/TbfTest.ok +++ b/tests/tbf/TbfTest.ok @@ -28,3 +28,5 @@ === end test_tbf_dl_reuse === === start test_tbf_gprs_egprs === === end test_tbf_gprs_egprs === +=== start test_tbf_ws === +=== end test_tbf_ws === |