aboutsummaryrefslogtreecommitdiffstats
path: root/tests/tbf/TbfTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tbf/TbfTest.cpp')
-rw-r--r--tests/tbf/TbfTest.cpp646
1 files changed, 406 insertions, 240 deletions
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index 8700347d..643551b9 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -26,7 +26,6 @@
#include "tbf_ul.h"
#include "gprs_ms.h"
#include "gprs_debug.h"
-#include "gprs_ms_storage.h"
#include "pcu_utils.h"
#include "gprs_bssgp_pcu.h"
#include "pcu_l1_if.h"
@@ -36,13 +35,14 @@
extern "C" {
#include "pcu_vty.h"
#include "coding_scheme.h"
+#include "alloc_algo.h"
#include <osmocom/core/application.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/vty/vty.h>
-#include <osmocom/gprs/protocol/gsm_04_60.h>
+#include <osmocom/gsm/protocol/gsm_44_060.h>
#include <osmocom/gsm/l1sap.h>
#include <osmocom/core/fsm.h>
}
@@ -67,6 +67,8 @@ static gprs_pcu *prepare_pcu(void)
{
struct gprs_pcu *pcu = gprs_pcu_alloc(tall_pcu_ctx);
bssgp_set_bssgp_callback(gprs_gp_send_test_cb, NULL);
+ osmo_tdef_set(pcu->T_defs, -2030, 0, OSMO_TDEF_S);
+ osmo_tdef_set(pcu->T_defs, -2031, 0, OSMO_TDEF_S);
return pcu;
}
@@ -78,7 +80,8 @@ static int bts_handle_rach(struct gprs_rlcmac_bts *bts, uint16_t ra, uint32_t Fn
.ra = ra,
.trx_nr = 0,
.ts_nr = 0,
- .rfn = Fn,
+ .rfn = fn2rfn(Fn),
+ .fn = Fn,
.qta = qta,
};
@@ -89,7 +92,7 @@ static void check_tbf(gprs_rlcmac_tbf *tbf)
{
OSMO_ASSERT(tbf);
if (tbf->state_is(TBF_ST_WAIT_RELEASE))
- OSMO_ASSERT(tbf->timers_pending(T3191) || osmo_timer_pending(&tbf->state_fsm.fi->timer));
+ OSMO_ASSERT(tbf->timers_pending(T3191) || osmo_timer_pending(&tbf->state_fi->timer));
if (tbf->state_is(TBF_ST_RELEASING))
OSMO_ASSERT(tbf->timers_pending(T_MAX));
}
@@ -120,45 +123,44 @@ static void test_tbf_tlli_update()
/*
* Make a uplink and downlink allocation
*/
- ms = bts_alloc_ms(bts, 0, 0);
- gprs_rlcmac_tbf *dl_tbf = tbf_alloc_dl_tbf(bts,
- ms, 0, false);
+ ms = ms_alloc(bts, NULL);
+ OSMO_ASSERT(ms_new_dl_tbf_assigned_on_pch(ms) == 0);
+ gprs_rlcmac_tbf *dl_tbf = ms_dl_tbf(ms);
OSMO_ASSERT(dl_tbf != NULL);
- dl_tbf->update_ms(0x2342, GPRS_RLCMAC_DL_TBF);
- dl_tbf->set_ta(4);
- OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);
OSMO_ASSERT(dl_tbf->ms() == ms);
+ ms_confirm_tlli(ms, 0x2342);
+ dl_tbf->set_ta(4);
- gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(bts,
- ms, 0, false);
+ OSMO_ASSERT(ms_new_ul_tbf_assigned_pacch(ms, 0));
+
+ gprs_rlcmac_tbf *ul_tbf = ms_ul_tbf(ms);
OSMO_ASSERT(ul_tbf != NULL);
- ul_tbf->update_ms(0x2342, GPRS_RLCMAC_UL_TBF);
- OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
OSMO_ASSERT(ul_tbf->ms() == ms);
+ ms_update_announced_tlli(ms, 0x2342);
- OSMO_ASSERT(bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI) == ms);
+ OSMO_ASSERT(bts_get_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI) == ms);
/*
* Now check.. that DL changes and that the timing advance
* has changed.
*/
- dl_tbf->update_ms(0x4232, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), 0x4232);
/* It is still there, since the new TLLI has not been used for UL yet */
- ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
+ ms_new = bts_get_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms == ms_new);
- ms_new = bts_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
+ ms_new = bts_get_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms == ms_new);
OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
/* Now use the new TLLI for UL */
- ul_tbf->update_ms(0x4232, GPRS_RLCMAC_UL_TBF);
- ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
+ ms_update_announced_tlli(ms, 0x4232);
+ ms_new = bts_get_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms_new == NULL);
- ms_new = bts_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
+ ms_new = bts_get_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms_new != NULL);
OSMO_ASSERT(ms_ta(ms_new) == 4);
@@ -190,42 +192,11 @@ static void setup_bts(struct gprs_rlcmac_bts *bts, uint8_t ts_no, uint8_t cs = 1
the_pcu->alloc_algorithm = alloc_algorithm_a;
bts->initial_cs_dl = cs;
bts->initial_cs_ul = cs;
- osmo_tdef_set(the_pcu->T_defs, -2030, 0, OSMO_TDEF_S);
- osmo_tdef_set(the_pcu->T_defs, -2031, 0, OSMO_TDEF_S);
trx = &bts->trx[0];
-
trx->pdch[ts_no].enable();
bts_set_current_frame_number(bts, DUMMY_FN);
}
-static gprs_rlcmac_dl_tbf *create_dl_tbf(struct gprs_rlcmac_bts *bts, uint8_t ms_class,
- uint8_t egprs_ms_class, uint8_t *trx_no_)
-{
- int tfi;
- uint8_t trx_no;
- GprsMs *ms;
- gprs_rlcmac_dl_tbf *dl_tbf;
-
- ms = bts_alloc_ms(bts, ms_class, egprs_ms_class);
-
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_DL_TBF, &trx_no, -1);
- OSMO_ASSERT(tfi >= 0);
- dl_tbf = tbf_alloc_dl_tbf(bts, ms, trx_no, true);
- OSMO_ASSERT(dl_tbf);
- dl_tbf->set_ta(0);
- check_tbf(dl_tbf);
-
- /* "Establish" the DL TBF */
- osmo_fsm_inst_dispatch(dl_tbf->dl_ass_fsm.fi, TBF_DL_ASS_EV_SCHED_ASS, NULL);
- osmo_fsm_inst_dispatch(dl_tbf->state_fsm.fi, TBF_EV_ASSIGN_ADD_CCCH, NULL);
- osmo_fsm_inst_dispatch(dl_tbf->state_fsm.fi, TBF_EV_ASSIGN_ACK_PACCH, NULL);
- check_tbf(dl_tbf);
-
- *trx_no_ = trx_no;
-
- return dl_tbf;
-}
-
static unsigned fn_add_blocks(unsigned fn, unsigned blocks)
{
unsigned bn = fn2bn(fn) + blocks;
@@ -235,11 +206,11 @@ static unsigned fn_add_blocks(unsigned fn, unsigned blocks)
}
static void request_dl_rlc_block(struct gprs_rlcmac_bts *bts,
- uint8_t trx_no, uint8_t ts_no,
+ struct gprs_rlcmac_pdch *pdch,
uint32_t *fn, uint8_t *block_nr = NULL)
{
uint8_t bn = fn2bn(*fn);
- gprs_rlcmac_rcv_rts_block(bts, trx_no, ts_no, *fn, bn);
+ gprs_rlcmac_rcv_rts_block(bts, pdch->trx->trx_no, pdch->ts_no, *fn, bn);
*fn = fn_add_blocks(*fn, 1);
bn += 1;
if (block_nr)
@@ -249,8 +220,37 @@ static void request_dl_rlc_block(struct gprs_rlcmac_bts *bts,
static void request_dl_rlc_block(struct gprs_rlcmac_tbf *tbf,
uint32_t *fn, uint8_t *block_nr = NULL)
{
- request_dl_rlc_block(tbf->bts, tbf->trx->trx_no,
- tbf->control_ts, fn, block_nr);
+ request_dl_rlc_block(tbf->bts, tbf->control_ts, fn, block_nr);
+}
+
+static gprs_rlcmac_dl_tbf *create_dl_tbf(struct gprs_rlcmac_bts *bts, uint8_t ms_class,
+ uint8_t egprs_ms_class, uint8_t *trx_no_)
+{
+ int tfi;
+ uint8_t trx_no;
+ GprsMs *ms;
+ gprs_rlcmac_dl_tbf *dl_tbf;
+
+ ms = ms_alloc(bts, NULL);
+ ms_set_ms_class(ms, ms_class);
+ ms_set_egprs_ms_class(ms, egprs_ms_class);
+
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_DL_TBF, &trx_no, -1);
+ OSMO_ASSERT(tfi >= 0);
+ OSMO_ASSERT(ms_new_dl_tbf_assigned_on_pch(ms) == 0);
+ dl_tbf = ms_dl_tbf(ms);
+ OSMO_ASSERT(dl_tbf);
+ dl_tbf->set_ta(0);
+ check_tbf(dl_tbf);
+
+ /* "Establish" the DL TBF */
+ osmo_fsm_inst_dispatch(dl_tbf->state_fi, TBF_EV_ASSIGN_ADD_CCCH, NULL);
+ osmo_fsm_inst_dispatch(dl_tbf->state_fi, TBF_EV_ASSIGN_READY_CCCH, NULL);
+ check_tbf(dl_tbf);
+
+ *trx_no_ = trx_no;
+
+ return dl_tbf;
}
enum test_tbf_final_ack_mode {
@@ -306,15 +306,15 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
setup_bts(bts, ts_no);
dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
- dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
- dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, llc_data, sizeof(llc_data));
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, llc_data, sizeof(llc_data));
/* Send only a few RLC/MAC blocks */
@@ -327,6 +327,13 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
OSMO_ASSERT(dl_tbf->have_data());
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
+ do {
+ /* Request to send one block */
+ request_dl_rlc_block(dl_tbf, &fn, &block_nr);
+ } while (dl_tbf->state_is(TBF_ST_FLOW));
+
+ OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FINISHED));
+
/* Queue a final ACK */
memset(rbb, 0, sizeof(rbb));
/* Receive a final ACK */
@@ -334,26 +341,29 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
/* Clean up and ensure tbfs are in the correct state */
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_WAIT_RELEASE));
+
+ /* Now append new data, a new DL TBF should be created and assigned through the old one due to T3192: */
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, llc_data, sizeof(llc_data));
new_tbf = ms_dl_tbf(ms);
check_tbf(new_tbf);
OSMO_ASSERT(new_tbf != dl_tbf);
OSMO_ASSERT(new_tbf->tfi() == 1);
check_tbf(dl_tbf);
if (test_mode == TEST_MODE_REVERSE_FREE) {
- ms_ref(ms);
+ ms_ref(ms, __func__);
tbf_free(new_tbf);
OSMO_ASSERT(ms_dl_tbf(ms) == NULL);
check_tbf(dl_tbf);
tbf_free(dl_tbf);
- ms_unref(ms);
+ ms_unref(ms, __func__);
} else {
- ms_ref(ms);
+ ms_ref(ms, __func__);
tbf_free(dl_tbf);
OSMO_ASSERT(ms_dl_tbf(ms) == new_tbf);
check_tbf(new_tbf);
tbf_free(new_tbf);
OSMO_ASSERT(ms_dl_tbf(ms) == NULL);
- ms_unref(ms);
+ ms_unref(ms, __func__);
}
TALLOC_FREE(the_pcu);
@@ -382,7 +392,7 @@ static void test_tbf_delayed_release()
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
@@ -390,8 +400,8 @@ static void test_tbf_delayed_release()
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Schedule two LLC frames */
- dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
- dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, llc_data, sizeof(llc_data));
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, llc_data, sizeof(llc_data));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
@@ -447,43 +457,43 @@ static void test_tbf_imsi()
dl_tbf[0] = create_dl_tbf(bts, ms_class, 0, &trx_no);
dl_tbf[1] = create_dl_tbf(bts, ms_class, 0, &trx_no);
- dl_tbf[0]->update_ms(0xf1000001, GPRS_RLCMAC_DL_TBF);
- dl_tbf[1]->update_ms(0xf1000002, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf[0]->ms(), 0xf1000001);
+ ms_confirm_tlli(dl_tbf[1]->ms(), 0xf1000002);
ms_set_imsi(dl_tbf[0]->ms(), "001001000000001");
- ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000001");
+ ms1 = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000001");
OSMO_ASSERT(ms1 != NULL);
- ms2 = bts_ms_store(bts)->get_ms(0xf1000001);
+ ms2 = bts_get_ms_by_tlli(bts, 0xf1000001, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 != NULL);
OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000001") == 0);
OSMO_ASSERT(ms1 == ms2);
/* change the IMSI on TBF 0 */
ms_set_imsi(dl_tbf[0]->ms(), "001001000000002");
- ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000001");
+ ms1 = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000001");
OSMO_ASSERT(ms1 == NULL);
- ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
+ ms1 = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000002");
OSMO_ASSERT(ms1 != NULL);
OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000002") == 0);
OSMO_ASSERT(ms1 == ms2);
/* use the same IMSI on TBF 1 */
{
- ms_ref(ms2);
+ ms_ref(ms2, __func__);
ms_set_imsi(dl_tbf[1]->ms(), "001001000000002");
- ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
+ ms1 = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000002");
OSMO_ASSERT(ms1 != NULL);
OSMO_ASSERT(ms1 != ms2);
OSMO_ASSERT(strcmp(ms_imsi(ms1), "001001000000002") == 0);
OSMO_ASSERT(strcmp(ms_imsi(ms2), "") == 0);
- ms_unref(ms2);
+ ms_unref(ms2, __func__);
}
- ms2 = bts_ms_store(bts)->get_ms(0xf1000001);
+ ms2 = bts_get_ms_by_tlli(bts, 0xf1000001, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 == NULL);
tbf_free(dl_tbf[1]);
- ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
+ ms1 = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000002");
OSMO_ASSERT(ms1 == NULL);
TALLOC_FREE(the_pcu);
@@ -529,7 +539,6 @@ static void test_tbf_exhaustion()
OSMO_ASSERT(rc == -EBUSY);
fprintf(stderr, "=== end %s ===\n", __func__);
- gprs_bssgp_destroy(bts);
TALLOC_FREE(the_pcu);
}
@@ -537,6 +546,7 @@ static void test_tbf_dl_llc_loss()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
uint8_t ts_no = 4;
uint8_t ms_class = 45;
int rc = 0;
@@ -556,6 +566,7 @@ static void test_tbf_dl_llc_loss()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no);
+ pdch = &bts->trx[0].pdch[ts_no];
/* keep the MS object 10 seconds */
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2030, 10, OSMO_TDEF_S) == 0);
@@ -567,7 +578,7 @@ static void test_tbf_dl_llc_loss()
delay_csec, buf, sizeof(buf));
OSMO_ASSERT(rc >= 0);
- ms = bts_ms_store(bts)->get_ms(0, 0, imsi);
+ ms = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, imsi);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
ms_dl_tbf(ms)->set_ta(0);
@@ -589,13 +600,13 @@ static void test_tbf_dl_llc_loss()
OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
- /* Here PCU would answer with data_cnf and trigger
+ /* Here BTS would answer with data_cnf and trigger
* bts_rcv_imm_ass_cnf(), which would trigger TBF_EV_ASSIGN_PCUIF_CNF.
* That in turn would set up timer X2002. Finally, X2002 timeout
* moves it to FLOW state. We set X2002 timeout to 0 here to get
* immediate trigger through osmo_select_main() */
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2002, 0, OSMO_TDEF_MS) == 0);
- osmo_fsm_inst_dispatch(ms_dl_tbf(ms)->state_fsm.fi, TBF_EV_ASSIGN_PCUIF_CNF, NULL);
+ osmo_fsm_inst_dispatch(ms_dl_tbf(ms)->state_fi, TBF_EV_ASSIGN_PCUIF_CNF, NULL);
osmo_select_main(0);
OSMO_ASSERT(ms_dl_tbf(ms)->state_is(TBF_ST_FLOW));
@@ -608,12 +619,13 @@ static void test_tbf_dl_llc_loss()
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x07, 0x00, 0x02, 0x4d, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
- { 0x07, 0x01, 0x04, 0x4d, 0x03, 0x03, 0x03,
+ /* On last DL block, PCU requests polling (DL ACK/NACK): S/P 1 and RRBP 01, hence 0x07 becomes 0xf1 */
+ { 0x1f, 0x01, 0x04, 0x4d, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
};
while (ms_dl_tbf(ms)->have_data()) {
- msg = ms_dl_tbf(ms)->create_dl_acked_block(fn += 4, 7);
+ msg = ms_dl_tbf(ms)->create_dl_acked_block(fn += 4, pdch);
fprintf(stderr, "MSG = %s\n", msgb_hexdump(msg));
if (!msgb_eq_data_print(msg, exp[expected_data - 1], GSM_MACBLOCK_LEN))
fprintf(stderr, "%s failed at %u\n", __func__, expected_data);
@@ -624,25 +636,32 @@ static void test_tbf_dl_llc_loss()
fprintf(stderr, "=== end %s ===\n", __func__);
- gprs_bssgp_destroy(bts);
+ /* Restore MS release timeout to 0 to make sure it is freed immediately: */
+ OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2030, 0, OSMO_TDEF_S) == 0);
TALLOC_FREE(the_pcu);
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_single_phase(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta)
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta)
{
GprsMs *ms;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- uint8_t trx_no = 0;
- struct gprs_rlcmac_pdch *pdch;
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
+ /* We set X2002 timeout to 0 here to get immediate trigger through osmo_select_main() below */
+ OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2002, 0, OSMO_TDEF_MS) == 0);
bts_handle_rach(bts, 0x03, *fn, qta);
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf != NULL);
+ OSMO_ASSERT(ul_tbf->state_is(TBF_ST_ASSIGN));
+
+ /* ImmAss has been sent PCU=PCUIF=>BTS. This means UL TBF is in state
+ * ASSIGN with X2002 armed. It will move to FLOW once it expires. */
+ osmo_select_main(0);
+ OSMO_ASSERT(ul_tbf->state_is(TBF_ST_FLOW));
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -654,10 +673,9 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_single_phase(struct gprs_rlcmac_bts
uint8_t(tlli >> 8), uint8_t(tlli), /* TLLI */
};
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
return ul_tbf;
@@ -671,13 +689,12 @@ static void send_ul_mac_block_buf(struct gprs_rlcmac_bts *bts, struct gprs_rlcma
pdch_ulc_expire_fn(pdch->ulc, fn);
}
-static void send_ul_mac_block(struct gprs_rlcmac_bts *bts, unsigned trx_no, unsigned ts_no,
+static void send_ul_mac_block(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_pdch *pdch,
RlcMacUplink_t *ulreq, unsigned fn)
{
bitvec *rlc_block;
uint8_t buf[64];
int num_bytes;
- struct gprs_rlcmac_pdch *pdch;
rlc_block = bitvec_alloc(23, tall_pcu_ctx);
@@ -686,14 +703,12 @@ static void send_ul_mac_block(struct gprs_rlcmac_bts *bts, unsigned trx_no, unsi
OSMO_ASSERT(size_t(num_bytes) < sizeof(buf));
bitvec_free(rlc_block);
- pdch = &bts->trx[trx_no].pdch[ts_no];
send_ul_mac_block_buf(bts, pdch, fn, &buf[0], num_bytes);
}
-static uint32_t get_poll_fn(struct gprs_rlcmac_tbf *tbf, uint8_t poll_ts)
+static uint32_t get_poll_fn(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_pdch *pdch)
{
- struct gprs_rlcmac_pdch *pdch = &tbf->trx->pdch[poll_ts];
struct pdch_ulc *ulc = pdch->ulc;
struct rb_node *node;
struct pdch_ulc_node *item;
@@ -716,33 +731,29 @@ static void send_control_ack(gprs_rlcmac_tbf *tbf)
ctrl_ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ctrl_ack->TLLI = tbf->tlli();
- send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
+ send_ul_mac_block(tbf->bts, tbf->control_ts,
&ulreq, get_poll_fn(tbf, tbf->control_ts));
}
-static void send_empty_block(gprs_rlcmac_tbf *tbf, unsigned ts_no, unsigned fn)
+static void send_empty_block(gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_pdch *pdch, unsigned fn)
{
- struct gprs_rlcmac_pdch *pdch;
- pdch = &tbf->bts->trx[tbf->trx->trx_no].pdch[ts_no];
send_ul_mac_block_buf(tbf->bts, pdch, fn, NULL, 0);
}
static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
- uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- struct gprs_rlcmac_pdch *pdch;
RlcMacUplink_t ulreq = {0};
struct gprs_rlc_ul_header_egprs_3 *egprs3 = NULL;
/* needed to set last_rts_fn in the PDCH object */
- request_dl_rlc_block(bts, trx_no, ts_no, fn);
+ request_dl_rlc_block(bts, pdch, fn);
/*
* simulate RACH, this sends an Immediate
@@ -751,7 +762,7 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
bts_handle_rach(bts, 0x73, rach_fn, qta);
/* get next free TFI */
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
@@ -779,10 +790,10 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
Multislot_capability.EGPRS_multislot_class = ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -801,10 +812,9 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
1, /* BSN:7, E:1 */
};
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data_msg[0], 23, *fn, &meas);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -832,7 +842,7 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
pdch->rcv_block(data_msg, 42, *fn, &meas);
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- struct msgb *msg1 = tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ struct msgb *msg1 = tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
static uint8_t exp1[] = { 0x40, 0x24, 0x01, 0x0b, 0x3e, 0x24, 0x46, 0x68, 0x9c, 0x70, 0x87, 0xb0,
0x06, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
@@ -860,7 +870,7 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
pdch->rcv_block(data_msg, 42, *fn, &meas);
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- msg1 = tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ msg1 = tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
static uint8_t exp2[] = { 0x40, 0x24, 0x01, 0x0b, 0x3e, 0x24, 0x46, 0x68, 0x9c, 0x70, 0x88, 0xb0,
0x06, 0x8b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
@@ -874,21 +884,19 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
- uint8_t trx_no = 0;
int tfi = 0, i = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- struct gprs_rlcmac_pdch *pdch;
RlcMacUplink_t ulreq = {0};
struct gprs_rlc_ul_header_egprs_3 *egprs3 = NULL;
/* needed to set last_rts_fn in the PDCH object */
- request_dl_rlc_block(bts, trx_no, ts_no, fn);
+ request_dl_rlc_block(bts, pdch, fn);
/*
* simulate RACH, this sends an Immediate
@@ -897,7 +905,7 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts
bts_handle_rach(bts, 0x73, rach_fn, qta);
/* get next free TFI */
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
@@ -925,10 +933,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts
Multislot_capability.EGPRS_multislot_class = ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -948,10 +956,9 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts
uint8_t(1), /* BSN:7, E:1 */
};
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data_msg[0], 23, *fn, &meas);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -1309,18 +1316,17 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
- uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
RlcMacUplink_t ulreq = {0};
/* needed to set last_rts_fn in the PDCH object */
- request_dl_rlc_block(bts, trx_no, ts_no, fn);
+ request_dl_rlc_block(bts, pdch, fn);
/*
* simulate RACH, this sends an Immediate
@@ -1329,7 +1335,7 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf(struct gprs_rlcmac_bts *bts,
bts_handle_rach(bts, 0x73, rach_fn, qta);
/* get next free TFI */
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
@@ -1356,10 +1362,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf(struct gprs_rlcmac_bts *bts,
MS_RA_capability_value[0].u.Content.
Multislot_capability.EGPRS_multislot_class = ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
/* send packet uplink assignment */
*fn = sba_fn;
request_dl_rlc_block(ul_tbf, fn);
@@ -1373,15 +1379,13 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf(struct gprs_rlcmac_bts *bts,
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class, gprs_rlcmac_ul_tbf *ul_tbf)
{
OSMO_ASSERT(ul_tbf);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
GprsMs *ms;
- uint8_t trx_no = 0;
int tfi = 0;
- struct gprs_rlcmac_pdch *pdch;
/* send fake data with cv=0*/
struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
@@ -1411,11 +1415,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct
data[5] = 0x0;
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
}
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
memset(data, 0x2b, sizeof(data));
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
hdr3->r = 0;
@@ -1437,7 +1440,6 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
request_dl_rlc_block(ul_tbf, fn);
@@ -1445,7 +1447,7 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct
check_tbf(ul_tbf);
OSMO_ASSERT(tbf_ul_ack_fi(ul_tbf)->state == TBF_UL_ACK_ST_NONE);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -1454,15 +1456,13 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class, gprs_rlcmac_ul_tbf *ul_tbf)
{
OSMO_ASSERT(ul_tbf);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
GprsMs *ms;
- uint8_t trx_no = 0;
int tfi = 0;
- struct gprs_rlcmac_pdch *pdch;
check_tbf(ul_tbf);
/* send fake data with cv=0*/
@@ -1494,11 +1494,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(stru
data[5] = 0x0;
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
}
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
memset(data, 0x2b, sizeof(data));
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
hdr3->r = 0;
@@ -1520,17 +1519,16 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(stru
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
request_dl_rlc_block(ul_tbf, fn);
check_tbf(ul_tbf);
OSMO_ASSERT(tbf_ul_ack_fi(ul_tbf)->state == TBF_UL_ACK_ST_NONE);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -1539,17 +1537,15 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(stru
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
- uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- struct gprs_rlcmac_pdch *pdch;
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -1582,11 +1578,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcm
data[5] = 0x0;
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
}
osmo_fsm_inst_dispatch(ul_tbf->ul_ack_fsm.fi, TBF_UL_ACK_EV_SCHED_ACK, NULL);
- tbf_ul_ack_create_rlcmac_msg(ul_tbf, *fn, ts_no);
+ tbf_ul_ack_create_rlcmac_msg(ul_tbf, pdch, *fn);
memset(data, 0x2b, sizeof(data));
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
hdr3->r = 0;
@@ -1608,7 +1603,6 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcm
data[6] = 0x2b;
data[7] = 0x2b;
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
request_dl_rlc_block(ul_tbf, fn);
@@ -1616,7 +1610,7 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcm
check_tbf(ul_tbf);
OSMO_ASSERT(tbf_ul_ack_fi(ul_tbf)->state == TBF_UL_ACK_ST_NONE);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -1624,26 +1618,24 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcm
return ul_tbf;
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
- uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- struct gprs_rlcmac_pdch *pdch;
RlcMacUplink_t ulreq = {0};
/* needed to set last_rts_fn in the PDCH object */
- request_dl_rlc_block(bts, trx_no, ts_no, fn);
+ request_dl_rlc_block(bts, pdch, fn);
/* simulate RACH, sends an Immediate Assignment Uplink on the AGCH */
bts_handle_rach(bts, 0x73, rach_fn, qta);
/* get next free TFI */
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
@@ -1670,10 +1662,10 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(struct gprs_rlcmac_bts *bt
EGPRS_multislot_class = ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -1693,10 +1685,9 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(struct gprs_rlcmac_bts *bt
uint8_t(1), /* BSN:7, E:1 */
};
- pdch = &bts->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas);
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -1709,17 +1700,16 @@ static void send_dl_data(struct gprs_rlcmac_bts *bts, uint32_t tlli, const char
{
GprsMs *ms, *ms2;
- ms = bts_ms_store(bts)->get_ms(tlli, 0, imsi);
+ ms = bts_get_ms(bts, tlli, GSM_RESERVED_TMSI, imsi);
dl_tbf_handle(bts, tlli, 0, imsi, 0, 0,
1000, data, data_size);
- ms = bts_ms_by_imsi(bts, imsi);
+ ms = bts_get_ms_by_imsi(bts, imsi);
OSMO_ASSERT(ms != NULL);
- OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
- if (imsi[0] && strcmp(imsi, "000") != 0) {
- ms2 = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ if (imsi[0] != '\0') {
+ ms2 = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms == ms2);
}
}
@@ -1731,7 +1721,7 @@ static void transmit_dl_data(struct gprs_rlcmac_bts *bts, uint32_t tlli, uint32_
GprsMs *ms;
unsigned ts_no;
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms);
dl_tbf = ms_dl_tbf(ms);
OSMO_ASSERT(dl_tbf);
@@ -1760,6 +1750,33 @@ static void test_tbf_single_phase()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
+ int ts_no = 7;
+ uint32_t fn = DUMMY_FN; /* 17,25,9 */
+ uint32_t tlli = 0xf1223344;
+ const char *imsi = "0011223344";
+ uint16_t qta = 31;
+ gprs_rlcmac_ul_tbf *ul_tbf;
+
+ fprintf(stderr, "=== start %s ===\n", __func__);
+
+ setup_bts(bts, ts_no);
+ pdch = &bts->trx[0].pdch[ts_no];
+
+ ul_tbf = establish_ul_tbf_single_phase(bts, pdch, tlli, &fn, qta);
+
+ print_ta_tlli(ul_tbf, true);
+ send_dl_data(bts, tlli, imsi, (const uint8_t *)"TEST", 4);
+
+ fprintf(stderr, "=== end %s ===\n", __func__);
+ TALLOC_FREE(the_pcu);
+}
+
+static void test_tbf_single_phase2()
+{
+ the_pcu = prepare_pcu();
+ struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = DUMMY_FN; /* 17,25,9 */
uint32_t tlli = 0xf1223344;
@@ -1770,12 +1787,21 @@ static void test_tbf_single_phase()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no);
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_single_phase(bts, ts_no, tlli, &fn, qta);
+ ul_tbf = establish_ul_tbf_single_phase(bts, pdch, tlli, &fn, qta);
print_ta_tlli(ul_tbf, true);
+ /* PCU sends CTRL ACK/NCK with FINAL_ACK=1, hence TBF is not in state FINISHED */
+ request_dl_rlc_block(bts, pdch, &fn);
+ OSMO_ASSERT(ul_tbf->state_is(TBF_ST_FINISHED));
+ /* Now data is sent but no DL TBF is created because MS is not reachable for DL Assignment */
send_dl_data(bts, tlli, imsi, (const uint8_t *)"TEST", 4);
+ /* After MS CTRL ACKs the FINAL_ACK=1 then it releases the TBF and goes
+ * to packet-idle mode. Hence PCU will trigger ImmAss(PktDlAss) on PCH. */
+ send_control_ack(ul_tbf);
+
fprintf(stderr, "=== end %s ===\n", __func__);
TALLOC_FREE(the_pcu);
}
@@ -1785,6 +1811,7 @@ static void test_tbf_egprs_two_phase_puan(void)
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
int ts_no = 7;
+ struct gprs_rlcmac_pdch *pdch;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
@@ -1802,10 +1829,11 @@ static void test_tbf_egprs_two_phase_puan(void)
bts->initial_mcs_dl = 9;
the_pcu->vty.ws_base = 128;
the_pcu->vty.ws_pdch = 64;
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf(bts, ts_no, tlli, &fn, qta, ms_class, egprs_ms_class);
+ ul_tbf = establish_ul_tbf(bts, pdch, tlli, &fn, qta, ms_class, egprs_ms_class);
/* Function to generate URBB with no length */
- ul_tbf = establish_ul_tbf_two_phase_puan_URBB_no_length(bts, ts_no, tlli, &fn,
+ ul_tbf = establish_ul_tbf_two_phase_puan_URBB_no_length(bts, pdch, tlli, &fn,
qta, ms_class, egprs_ms_class, ul_tbf);
print_ta_tlli(ul_tbf, true);
@@ -1813,7 +1841,7 @@ static void test_tbf_egprs_two_phase_puan(void)
static_cast<gprs_rlc_ul_window *>(ul_tbf->window())->reset_state();
/* Function to generate URBB with length */
- ul_tbf = establish_ul_tbf_two_phase_puan_URBB_with_length(bts, ts_no, tlli, &fn,
+ ul_tbf = establish_ul_tbf_two_phase_puan_URBB_with_length(bts, pdch, tlli, &fn,
qta, ms_class, egprs_ms_class, ul_tbf);
print_ta_tlli(ul_tbf, true);
@@ -1823,7 +1851,7 @@ static void test_tbf_egprs_two_phase_puan(void)
/* Function to generate CRBB */
the_pcu->vty.ws_base = 128;
the_pcu->vty.ws_pdch = 64;
- ul_tbf = establish_ul_tbf_two_phase_puan_CRBB(bts, ts_no, tlli, &fn,
+ ul_tbf = establish_ul_tbf_two_phase_puan_CRBB(bts, pdch, tlli, &fn,
qta, ms_class, egprs_ms_class);
print_ta_tlli(ul_tbf, true);
@@ -1925,8 +1953,8 @@ static void test_tbf_two_phase()
setup_bts(bts, ts_no, 4);
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli, &fn, qta,
- ms_class, 0);
+ ul_tbf = establish_ul_tbf_two_phase(bts, &bts->trx[0].pdch[ts_no],
+ tlli, &fn, qta, ms_class, 0);
print_ta_tlli(ul_tbf, true);
send_dl_data(bts, tlli, imsi, (const uint8_t *)"TEST", 4);
@@ -1945,6 +1973,7 @@ static void test_tbf_ra_update_rach()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -1959,8 +1988,9 @@ static void test_tbf_ra_update_rach()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 4);
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli1, &fn, qta,
ms_class, 0);
ms1 = ul_tbf->ms();
@@ -1987,7 +2017,7 @@ static void test_tbf_ra_update_rach()
fn = fn_add_blocks(fn, 1);
/* Now establish a new TBF for the RA UPDATE COMPLETE (new TLLI) */
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli2, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli2, &fn, qta,
ms_class, 0);
ms2 = ul_tbf->ms();
@@ -2000,14 +2030,14 @@ static void test_tbf_ra_update_rach()
* the PCU can see, that both MS objects belong to same MS */
send_dl_data(bts, tlli2, imsi, (const uint8_t *)"DATA", 4);
- ms = bts_ms_by_imsi(bts, imsi);
+ ms = bts_get_ms_by_imsi(bts, imsi);
OSMO_ASSERT(ms == ms2);
print_ms(ms2, false);
- ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms == NULL);
- ms = bts_ms_by_tlli(bts, tlli2, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli2, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms == ms2);
TALLOC_FREE(the_pcu);
@@ -2018,6 +2048,7 @@ static void test_tbf_dl_flow_and_rach_two_phase()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2031,8 +2062,9 @@ static void test_tbf_dl_flow_and_rach_two_phase()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 1);
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli1, &fn, qta,
ms_class, 0);
ms1 = ul_tbf->ms();
@@ -2048,11 +2080,11 @@ static void test_tbf_dl_flow_and_rach_two_phase()
/* Get rid of old UL TBF */
tbf_free(ul_tbf);
- ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms1 == ms);
/* Now establish a new UL TBF, this will consume one LLC packet */
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli1, &fn, qta,
ms_class, 0);
ms2 = ul_tbf->ms();
@@ -2061,7 +2093,7 @@ static void test_tbf_dl_flow_and_rach_two_phase()
/* This should be the same MS object */
OSMO_ASSERT(ms2 == ms1);
- ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 == ms);
/* A DL TBF should still exist */
@@ -2079,6 +2111,7 @@ static void test_tbf_dl_flow_and_rach_single_phase()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2092,8 +2125,9 @@ static void test_tbf_dl_flow_and_rach_single_phase()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 1);
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli1, &fn, qta,
ms_class, 0);
ms1 = ul_tbf->ms();
@@ -2109,11 +2143,11 @@ static void test_tbf_dl_flow_and_rach_single_phase()
/* Get rid of old UL TBF */
tbf_free(ul_tbf);
- ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms1 == ms);
/* Now establish a new UL TBF */
- ul_tbf = establish_ul_tbf_single_phase(bts, ts_no, tlli1, &fn, qta);
+ ul_tbf = establish_ul_tbf_single_phase(bts, pdch, tlli1, &fn, qta);
ms2 = ul_tbf->ms();
print_ms(ms2, false);
@@ -2121,7 +2155,7 @@ static void test_tbf_dl_flow_and_rach_single_phase()
/* There should be a different MS object */
OSMO_ASSERT(ms2 != ms1);
- ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 == ms);
OSMO_ASSERT(ms1 != ms);
@@ -2139,6 +2173,7 @@ static void test_tbf_dl_reuse()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2154,8 +2189,9 @@ static void test_tbf_dl_reuse()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 1);
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli1, &fn, qta,
ms_class, 0);
ms1 = ul_tbf->ms();
@@ -2210,13 +2246,13 @@ static void test_tbf_dl_reuse()
ack->DOWNLINK_TFI = dl_tbf1->tfi();
ack->Ack_Nack_Description.FINAL_ACK_INDICATION = 1;
- send_ul_mac_block(bts, 0, dl_tbf1->control_ts, &ulreq, get_poll_fn(dl_tbf1, dl_tbf1->control_ts));
+ send_ul_mac_block(bts, dl_tbf1->control_ts, &ulreq, get_poll_fn(dl_tbf1, dl_tbf1->control_ts));
OSMO_ASSERT(dl_tbf1->state_is(TBF_ST_WAIT_RELEASE));
request_dl_rlc_block(dl_tbf1, &fn);
- ms2 = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
+ ms2 = bts_get_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 == ms1);
OSMO_ASSERT(ms_dl_tbf(ms2));
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(TBF_ST_ASSIGN));
@@ -2272,14 +2308,12 @@ static void test_tbf_gprs_egprs()
OSMO_ASSERT(rc == 0);
fprintf(stderr, "=== end %s ===\n", __func__);
- gprs_bssgp_destroy(bts);
TALLOC_FREE(the_pcu);
}
static inline void ws_check(gprs_rlcmac_dl_tbf *dl_tbf, const char *test, uint8_t exp_slots, uint16_t exp_ws,
- bool free, bool end)
+ bool free)
{
- gprs_rlcmac_bts *bts = dl_tbf->bts;
if (!dl_tbf) {
fprintf(stderr, "%s(): FAILED (NULL TBF)\n", test);
return;
@@ -2298,11 +2332,6 @@ static inline void ws_check(gprs_rlcmac_dl_tbf *dl_tbf, const char *test, uint8_
if (free)
tbf_free(dl_tbf);
-
- if (end) {
- fprintf(stderr, "=== end %s ===\n", test);
- gprs_bssgp_destroy(bts);
- }
}
static void test_tbf_ws()
@@ -2335,18 +2364,26 @@ static void test_tbf_ws()
gprs_bssgp_init(bts, 4234, 4234, 1, 1, false, 0, 0, 0);
/* Does no support EGPRS */
- ms = bts_alloc_ms(bts, ms_class, 0);
- dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, false);
+ ms = ms_alloc(bts, NULL);
+ ms_set_ms_class(ms, ms_class);
+ OSMO_ASSERT(ms_new_dl_tbf_assigned_on_pch(ms) == 0);
+ dl_tbf = ms_dl_tbf(ms);
+ OSMO_ASSERT(dl_tbf);
- ws_check(dl_tbf, __func__, 4, 64, true, false);
+ ws_check(dl_tbf, __func__, 4, 64, true);
/* EGPRS-only */
/* Does support EGPRS */
- ms = bts_alloc_ms(bts, ms_class, ms_class);
- dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, false);
+ ms = ms_alloc(bts, NULL);
+ ms_set_ms_class(ms, ms_class);
+ ms_set_egprs_ms_class(ms, ms_class);
+ OSMO_ASSERT(ms_new_dl_tbf_assigned_on_pch(ms) == 0);
+ dl_tbf = ms_dl_tbf(ms);
+ OSMO_ASSERT(dl_tbf);
- ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true, true);
+ ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true);
+ fprintf(stderr, "=== end %s ===\n", __func__);
TALLOC_FREE(the_pcu);
}
@@ -2382,15 +2419,116 @@ static void test_tbf_update_ws(void)
/* EGPRS-only */
/* Does support EGPRS */
- ms = bts_alloc_ms(bts, ms_class, ms_class);
- dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, true);
+ ms = ms_alloc(bts, NULL);
+ ms_set_ms_class(ms, ms_class);
+ ms_set_egprs_ms_class(ms, ms_class);
+ OSMO_ASSERT(ms_new_dl_tbf_assigned_on_pch(ms) == 0);
+ dl_tbf = ms_dl_tbf(ms);
+ OSMO_ASSERT(dl_tbf);
- ws_check(dl_tbf, __func__, 1, 128 + 1 * 64, false, false);
+ ws_check(dl_tbf, __func__, 1, 128 + 1 * 64, false);
- dl_tbf->update();
+ OSMO_ASSERT(dl_tbf_upgrade_to_multislot(dl_tbf) == 0);
/* window size should be 384 */
- ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true, true);
+ ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true);
+ fprintf(stderr, "=== end %s ===\n", __func__);
+ TALLOC_FREE(the_pcu);
+}
+
+/* Test DL-TBF first assigned over CCCH ImmAss, then after X2002 timeout, when MS
+is available to receive from TBF on PACCH, upgrade it to multislot. In the
+middle the MS would request a new UL-TBF and PCU ends up creating 2 MS objects on
+different TRX, which are eventually merged.
+Hence, new multislot DL-TBF allocation (assigned over PACCH) happens on a different TRX
+than the one which was assigned over CCCH and where the PktDlAss is sent. SYS#6231 */
+static void test_ms_merge_dl_tbf_different_trx(void)
+{
+ the_pcu = prepare_pcu();
+ struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ GprsMs *first_ms, *second_ms;
+ uint8_t ts_no = 1;
+ uint8_t ms_class = 11;
+ struct gprs_rlcmac_trx *trx0 = &bts->trx[0];
+ struct gprs_rlcmac_trx *trx1 = &bts->trx[1];
+ uint32_t old_tlli = 0xa3c2f953;
+ uint32_t new_tlli = 0xecc1f953;
+ const char *imsi = "001001000000001";
+ uint8_t llc_buf[19];
+ int rc;
+ unsigned delay_csec = 1000;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
+ struct gprs_rlcmac_ul_tbf *ul_tbf;
+ uint32_t fn = 0;
+
+ fprintf(stderr, "=== start %s ===\n", __func__);
+
+ bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
+ if (!bts->pcu->nsi) {
+ LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
+ abort();
+ }
+
+ setup_bts(bts, ts_no);
+ the_pcu->alloc_algorithm = alloc_algorithm_b;
+ /* trx0->pdch[ts_no].enable(); Already enabled during setup_bts()) */
+ trx0->pdch[ts_no].disable();
+ trx1->pdch[4].enable();
+ trx1->pdch[5].enable();
+ trx1->pdch[6].enable();
+ gprs_bssgp_init(bts, 5234, 5234, 1, 1, false, 0, 0, 0);
+
+ /* Handle LLC frame 1. This will create the TBF we want in TRX1 and
+ * we'll have it upgrade to multislot on TRX0 later. This will trigger a
+ * CCCH Dl ImAss towards BTS PCUIF. The confirmation from BTS is
+ * injected further below (TBF_EV_ASSIGN_PCUIF_CNF). */
+ memset(llc_buf, 1, sizeof(llc_buf));
+ rc = dl_tbf_handle(bts, old_tlli, 0, imsi, ms_class, 0,
+ delay_csec, llc_buf, sizeof(llc_buf));
+ OSMO_ASSERT(rc >= 0);
+
+ first_ms = bts_get_ms(bts, GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, imsi);
+ OSMO_ASSERT(first_ms);
+ dl_tbf = ms_dl_tbf(first_ms);
+ OSMO_ASSERT(dl_tbf);
+ OSMO_ASSERT(tbf_get_trx(dl_tbf) == trx1);
+ OSMO_ASSERT(dl_tbf->control_ts->trx == trx1);
+ struct gprs_rlcmac_pdch *old_dl_control_ts = dl_tbf->control_ts;
+
+ /* Enable PDCHs on TRX0 so that second_ms is allocated on TRX0: */
+ trx0->pdch[1].enable();
+ trx0->pdch[2].enable();
+ trx0->pdch[3].enable();
+
+ second_ms = ms_alloc(bts, NULL);
+ ms_set_tlli(second_ms, new_tlli);
+ OSMO_ASSERT(ms_new_ul_tbf_assigned_pacch(second_ms, 0));
+ ul_tbf = ms_ul_tbf(second_ms);
+ OSMO_ASSERT(ul_tbf != NULL);
+ ms_update_announced_tlli(second_ms, new_tlli);
+
+ /* Here PCU gets to know the MS are the same and they get merged. */
+ rc = dl_tbf_handle(bts, new_tlli, old_tlli, imsi, ms_class, 0,
+ delay_csec, llc_buf, sizeof(llc_buf));
+ OSMO_ASSERT(rc >= 0);
+ /* Here we assert a new DL-TBF is created in the new MS (hence old from TRX1 is deleted and new one is in TRX0): */
+ dl_tbf = ms_dl_tbf(second_ms);
+ OSMO_ASSERT(tbf_get_trx(dl_tbf) == trx0);
+ OSMO_ASSERT(dl_tbf->control_ts != old_dl_control_ts);
+ OSMO_ASSERT(dl_tbf == llist_first_entry_or_null(&trx0->dl_tbfs, struct llist_item, list)->entry);
+ OSMO_ASSERT(NULL == llist_first_entry_or_null(&trx1->dl_tbfs, struct llist_item, list));
+
+ /* Here BTS would answer with data_cnf and trigger
+ * bts_rcv_imm_ass_cnf(), which would trigger TBF_EV_ASSIGN_PCUIF_CNF.
+ * Since that's for an older DL-TBF assignment which no longer exists, it is ignored. */
+ OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2002, 0, OSMO_TDEF_MS) == 0);
+ osmo_fsm_inst_dispatch(ms_dl_tbf(second_ms)->state_fi, TBF_EV_ASSIGN_PCUIF_CNF, NULL);
+ osmo_select_main(0);
+
+ /* get the PACCH PktDlAss for the DL-TBF, allocated on the UL-TBF from the new MS obj: */
+ request_dl_rlc_block(dl_tbf->bts, dl_tbf->control_ts, &fn);
+
+ fprintf(stderr, "=== end %s ===\n", __func__);
TALLOC_FREE(the_pcu);
}
@@ -2398,6 +2536,7 @@ static void test_tbf_puan_urbb_len(void)
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2414,8 +2553,9 @@ static void test_tbf_puan_urbb_len(void)
setup_bts(bts, ts_no, 4);
bts->initial_mcs_dl = 9;
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = puan_urbb_len_issue(bts, ts_no, tlli, &fn, qta,
+ ul_tbf = puan_urbb_len_issue(bts, pdch, tlli, &fn, qta,
ms_class, egprs_ms_class);
print_ta_tlli(ul_tbf, true);
@@ -2426,16 +2566,14 @@ static void test_tbf_puan_urbb_len(void)
}
static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
- uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
+ struct gprs_rlcmac_pdch *pdch, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
- uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
- struct gprs_rlcmac_pdch *pdch;
RlcMacUplink_t ulreq = {0};
struct gprs_rlc_ul_header_egprs_3 *egprs3 = NULL;
Packet_Resource_Request_t *presreq = NULL;
@@ -2443,7 +2581,7 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
Multislot_capability_t *pmultislotcap = NULL;
/* needed to set last_rts_fn in the PDCH object */
- request_dl_rlc_block(bts, trx_no, ts_no, fn);
+ request_dl_rlc_block(bts, pdch, fn);
/*
* simulate RACH, this sends an Immediate
@@ -2452,7 +2590,7 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
bts_handle_rach(bts, 0x73, rach_fn, qta);
/* get next free TFI */
- tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
+ tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &pdch->trx->trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
@@ -2475,10 +2613,10 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
pmultislotcap->EGPRS_multislot_class = ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
/* check the TBF */
- ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
+ ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, pdch->trx->trx_no, pdch->ts_no);
OSMO_ASSERT(ul_tbf);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
@@ -2493,9 +2631,7 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
uint8_t data_msg[49] = {0};
- pdch = &bts->trx[trx_no].pdch[ts_no];
-
- ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
+ ms = bts_get_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms_ta(ms) == qta/4);
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
@@ -2528,7 +2664,7 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
data_msg[5] = 0x0;
pdch->rcv_block(data_msg, 49, *fn, &meas);
- OSMO_ASSERT(ul_tbf->m_llc.m_index == 43);
+ OSMO_ASSERT(ul_tbf->m_llc.index == 43);
return ul_tbf;
}
@@ -2537,6 +2673,7 @@ static void test_tbf_li_decoding(void)
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2553,8 +2690,9 @@ static void test_tbf_li_decoding(void)
setup_bts(bts, ts_no, 4);
bts->initial_mcs_dl = 9;
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = tbf_li_decoding(bts, ts_no, tlli, &fn, qta,
+ ul_tbf = tbf_li_decoding(bts, pdch, tlli, &fn, qta,
ms_class, egprs_ms_class);
print_ta_tlli(ul_tbf, true);
@@ -2609,7 +2747,7 @@ static void test_tbf_epdan_out_of_rx_window(void)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
prlcdlwindow = static_cast<gprs_rlc_dl_window *>(dl_tbf->window());
prlcmvb = &prlcdlwindow->m_v_b;
prlcdlwindow->m_v_s = 1288;
@@ -2664,6 +2802,7 @@ static void test_tbf_egprs_two_phase_spb(void)
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2680,8 +2819,9 @@ static void test_tbf_egprs_two_phase_spb(void)
setup_bts(bts, ts_no, 4);
bts->initial_mcs_dl = 9;
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase_spb(bts, ts_no, tlli, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase_spb(bts, pdch, tlli, &fn, qta,
ms_class, egprs_ms_class);
print_ta_tlli(ul_tbf, true);
@@ -2695,6 +2835,7 @@ static void test_tbf_egprs_two_phase()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
@@ -2711,8 +2852,9 @@ static void test_tbf_egprs_two_phase()
setup_bts(bts, ts_no, 4);
bts->initial_mcs_dl = 9;
+ pdch = &bts->trx[0].pdch[ts_no];
- ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli, &fn, qta,
+ ul_tbf = establish_ul_tbf_two_phase(bts, pdch, tlli, &fn, qta,
ms_class, egprs_ms_class);
print_ta_tlli(ul_tbf, true);
@@ -2742,7 +2884,7 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
bts->initial_mcs_dl = mcs;
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
@@ -2750,7 +2892,7 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Schedule a small LLC frame */
- dl_tbf->append_data(1000, test_data, 10);
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, test_data, 10);
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
@@ -2762,7 +2904,7 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
/* Schedule a large LLC frame */
- dl_tbf->append_data(1000, test_data, sizeof(test_data));
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, test_data, sizeof(test_data));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
@@ -2771,9 +2913,16 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
/* Request to send one RLC/MAC block */
request_dl_rlc_block(dl_tbf, &fn);
}
+ /* ACK all blocks */
+ memset(rbb, 0xff, sizeof(rbb));
+ _rcv_ack(false, dl_tbf, rbb);
+ /* X2031 may keep the TBF open for a while: */
+ while (dl_tbf->state_is(TBF_ST_FLOW)) {
+ request_dl_rlc_block(dl_tbf, &fn);
+ }
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
- OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
+ OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FINISHED));
_rcv_ack(true, dl_tbf, rbb); /* Receive a final ACK */
@@ -2799,7 +2948,7 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
bts->initial_mcs_dl = mcs;
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
for (i = 0; i < sizeof(test_data); i++)
test_data[i] = i%256;
@@ -2811,7 +2960,7 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
* 2 RLC data blocks. Which are enough to test Header Type 1
* cases
*/
- dl_tbf->append_data(1000, test_data, 100);
+ ms_append_llc_dl_data(dl_tbf->ms(), 1000, test_data, 100);
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
@@ -2822,6 +2971,19 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf)
{
uint8_t rbb[64/8];
+ uint32_t fn = 0;
+
+ if (dl_tbf->state_is(TBF_ST_FLOW)) {
+ /* X2031 may keep the TBF open for a while: */
+ while (dl_tbf->state_is(TBF_ST_FLOW)) {
+ /* ACK all blocks */
+ memset(rbb, 0xff, sizeof(rbb));
+ _rcv_ack(false, dl_tbf, rbb);
+ request_dl_rlc_block(dl_tbf, &fn);
+ }
+ }
+
+ OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FINISHED));
_rcv_ack(true, dl_tbf, rbb); /* Receive a final ACK */
@@ -3113,7 +3275,6 @@ static void establish_and_use_egprs_dl_tbf_for_retx(struct gprs_rlcmac_bts *bts,
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
}
/* Clean up pending items in UL controller: */
- send_empty_block(dl_tbf, dl_tbf->control_ts, fn+50);
tbf_cleanup(dl_tbf);
}
@@ -3202,6 +3363,7 @@ static void test_packet_access_rej_prr_no_other_tbfs()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
uint32_t fn = 2654218;
int ts_no = 7;
uint8_t trx_no = 0;
@@ -3212,21 +3374,21 @@ static void test_packet_access_rej_prr_no_other_tbfs()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 4);
+ pdch = &bts->trx[trx_no].pdch[ts_no];
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2000, 0, OSMO_TDEF_MS) == 0);
int rc = 0;
- ms = bts_alloc_ms(bts, 0, 0);
+ ms = ms_alloc(bts, NULL);
ms_set_tlli(ms, tlli);
- ul_tbf = handle_tbf_reject(bts, ms, trx_no, ts_no);
+ ul_tbf = ms_new_ul_tbf_rejected_pacch(ms, pdch);
OSMO_ASSERT(ul_tbf != 0);
/* trigger packet access reject */
uint8_t bn = fn2bn(fn);
- rc = gprs_rlcmac_rcv_rts_block(bts,
- trx_no, ts_no, fn, bn);
+ rc = gprs_rlcmac_rcv_rts_block(bts, pdch->trx->trx_no, pdch->ts_no, fn, bn);
OSMO_ASSERT(rc == 0);
osmo_select_main(0);
@@ -3239,6 +3401,7 @@ static void test_packet_access_rej_prr()
{
the_pcu = prepare_pcu();
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
+ struct gprs_rlcmac_pdch *pdch;
uint32_t fn = 2654218;
uint16_t qta = 31;
int ts_no = 7;
@@ -3256,6 +3419,7 @@ static void test_packet_access_rej_prr()
fprintf(stderr, "=== start %s ===\n", __func__);
setup_bts(bts, ts_no, 4);
+ pdch = &bts->trx[trx_no].pdch[ts_no];
int rc = 0;
@@ -3290,14 +3454,13 @@ static void test_packet_access_rej_prr()
pmultislotcap->EGPRS_multislot_class = egprs_ms_class;
}
- send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
+ send_ul_mac_block(bts, pdch, &ulreq, sba_fn);
sba_fn = fn_next_block(sba_fn);
/* trigger packet access reject */
uint8_t bn = fn2bn(fn);
- rc = gprs_rlcmac_rcv_rts_block(bts,
- trx_no, ts_no, fn, bn);
+ rc = gprs_rlcmac_rcv_rts_block(bts, pdch->trx->trx_no, pdch->ts_no, fn, bn);
OSMO_ASSERT(rc == 0);
}
@@ -3319,7 +3482,7 @@ void test_packet_access_rej_epdan()
setup_bts(bts, 4);
static gprs_rlcmac_dl_tbf *dl_tbf = tbf_init(bts, 1);
- dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+ ms_confirm_tlli(dl_tbf->ms(), tlli);
osmo_fsm_inst_dispatch(dl_tbf->ul_ass_fsm.fi, TBF_UL_ASS_EV_SCHED_ASS_REJ, NULL);
struct msgb *msg = tbf_ul_ass_create_rlcmac_msg((const struct gprs_rlcmac_tbf*)dl_tbf, 0, 0);
@@ -3351,7 +3514,7 @@ int main(int argc, char **argv)
log_set_print_category_hex(osmo_stderr_target, 0);
log_parse_category_mask(osmo_stderr_target, "DRLCMAC,1:DRLCMACDATA,3:DRLCMACDL,3:DRLCMACUL,3:"
"DRLCMACSCHED,1:DRLCMACMEAS,3:DNS,3:DLBSSGP,3:DPCU,5:"
- "DL1IF,6:DTBF,1:DTBFUL,1:DTBFDL,1:DLGLOBAL,2:");
+ "DL1IF,6:DMS,1:DTBF,1:DTBFUL,1:DTBFDL,1:DLGLOBAL,2:");
osmo_fsm_log_addr(false);
vty_init(&pcu_vty_info);
pcu_vty_init();
@@ -3369,6 +3532,7 @@ int main(int argc, char **argv)
test_tbf_exhaustion();
test_tbf_dl_llc_loss();
test_tbf_single_phase();
+ test_tbf_single_phase2();
test_tbf_two_phase();
test_tbf_ra_update_rach();
test_tbf_dl_flow_and_rach_two_phase();
@@ -3390,6 +3554,7 @@ int main(int argc, char **argv)
test_packet_access_rej_epdan();
test_packet_access_rej_prr();
test_packet_access_rej_prr_no_other_tbfs();
+ test_ms_merge_dl_tbf_different_trx();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
@@ -3402,6 +3567,7 @@ int main(int argc, char **argv)
extern "C" {
void l1if_pdch_req() { abort(); }
void l1if_connect_pdch() { abort(); }
-void l1if_close_pdch() { abort(); }
-void l1if_open_pdch() { abort(); }
+void l1if_disconnect_pdch() { abort(); }
+void l1if_close_trx() { abort(); }
+void l1if_open_trx() { abort(); }
}