2013-10-30 13:50:17 +00:00
|
|
|
/*
|
|
|
|
* TbfTest.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 by Holger Hans Peter Freyther
|
|
|
|
*
|
|
|
|
* All Rights Reserved
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "bts.h"
|
|
|
|
#include "tbf.h"
|
2021-01-14 15:48:38 +00:00
|
|
|
#include "tbf_dl.h"
|
2019-09-25 15:47:02 +00:00
|
|
|
#include "tbf_ul.h"
|
2021-01-14 15:48:38 +00:00
|
|
|
#include "gprs_ms.h"
|
2013-10-30 13:50:17 +00:00
|
|
|
#include "gprs_debug.h"
|
2021-01-14 15:48:38 +00:00
|
|
|
#include "gprs_ms_storage.h"
|
2015-03-25 09:48:52 +00:00
|
|
|
#include "pcu_utils.h"
|
2015-04-09 17:17:21 +00:00
|
|
|
#include "gprs_bssgp_pcu.h"
|
2015-05-27 11:03:15 +00:00
|
|
|
#include "pcu_l1_if.h"
|
2016-10-25 07:15:24 +00:00
|
|
|
#include "decoding.h"
|
2018-01-26 12:31:42 +00:00
|
|
|
#include <gprs_rlcmac.h>
|
2013-10-30 13:50:17 +00:00
|
|
|
|
|
|
|
extern "C" {
|
2015-04-09 17:17:21 +00:00
|
|
|
#include "pcu_vty.h"
|
2020-05-18 09:35:35 +00:00
|
|
|
#include "coding_scheme.h"
|
2015-04-09 17:17:21 +00:00
|
|
|
|
2013-10-30 13:50:17 +00:00
|
|
|
#include <osmocom/core/application.h>
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/core/utils.h>
|
2015-04-09 17:17:21 +00:00
|
|
|
#include <osmocom/vty/vty.h>
|
2016-07-26 12:56:21 +00:00
|
|
|
#include <osmocom/gprs/protocol/gsm_04_60.h>
|
2016-08-17 09:47:21 +00:00
|
|
|
#include <osmocom/gsm/l1sap.h>
|
2013-10-30 13:50:17 +00:00
|
|
|
}
|
|
|
|
|
2015-04-09 17:17:21 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
2016-11-07 12:07:36 +00:00
|
|
|
#define DUMMY_FN 2654167
|
|
|
|
|
2013-10-30 13:50:17 +00:00
|
|
|
void *tall_pcu_ctx;
|
|
|
|
int16_t spoof_mnc = 0, spoof_mcc = 0;
|
2018-02-20 23:39:07 +00:00
|
|
|
bool spoof_mnc_3_digits = false;
|
2013-10-30 13:50:17 +00:00
|
|
|
|
2019-11-07 21:44:04 +00:00
|
|
|
/* Measurements shared by all unit tests */
|
|
|
|
static struct pcu_l1_meas meas;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static int bts_handle_rach(struct gprs_rlcmac_bts *bts, uint16_t ra, uint32_t Fn, int16_t qta)
|
2020-05-21 12:55:46 +00:00
|
|
|
{
|
|
|
|
struct rach_ind_params rip = {
|
|
|
|
.burst_type = GSM_L1_BURST_TYPE_ACCESS_0,
|
|
|
|
.is_11bit = false,
|
|
|
|
.ra = ra,
|
|
|
|
.trx_nr = 0,
|
|
|
|
.ts_nr = 0,
|
|
|
|
.rfn = Fn,
|
|
|
|
.qta = qta,
|
|
|
|
};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
return bts_rcv_rach(bts, &rip);
|
2020-05-21 12:55:46 +00:00
|
|
|
}
|
|
|
|
|
2015-02-23 14:10:20 +00:00
|
|
|
static void check_tbf(gprs_rlcmac_tbf *tbf)
|
|
|
|
{
|
|
|
|
OSMO_ASSERT(tbf);
|
2015-08-13 16:36:56 +00:00
|
|
|
if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
|
2017-12-20 16:31:13 +00:00
|
|
|
OSMO_ASSERT(tbf->timers_pending(T3191) || tbf->timers_pending(T3193));
|
2015-08-13 16:36:56 +00:00
|
|
|
if (tbf->state_is(GPRS_RLCMAC_RELEASING))
|
2017-12-20 16:31:13 +00:00
|
|
|
OSMO_ASSERT(tbf->timers_pending(T_MAX));
|
2015-02-23 14:10:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-29 12:18:46 +00:00
|
|
|
static void test_tbf_base()
|
|
|
|
{
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-06-29 12:18:46 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(GPRS_RLCMAC_DL_TBF == reverse(GPRS_RLCMAC_UL_TBF));
|
|
|
|
OSMO_ASSERT(GPRS_RLCMAC_UL_TBF == reverse(GPRS_RLCMAC_DL_TBF));
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-06-29 12:18:46 +00:00
|
|
|
}
|
|
|
|
|
2013-10-30 13:50:17 +00:00
|
|
|
static void test_tbf_tlli_update()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-05-15 13:50:43 +00:00
|
|
|
GprsMs *ms, *ms_new;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-01-11 15:12:01 +00:00
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2021-01-13 17:54:38 +00:00
|
|
|
the_pcu->alloc_algorithm = alloc_algorithm_a;
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->trx[0].pdch[2].enable();
|
|
|
|
bts->trx[0].pdch[3].enable();
|
2013-10-30 13:50:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a uplink and downlink allocation
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_alloc_ms(bts, 0, 0);
|
|
|
|
gprs_rlcmac_tbf *dl_tbf = tbf_alloc_dl_tbf(bts,
|
2020-05-08 16:15:59 +00:00
|
|
|
ms, 0, false);
|
2015-06-29 11:03:46 +00:00
|
|
|
OSMO_ASSERT(dl_tbf != NULL);
|
2015-05-18 12:35:11 +00:00
|
|
|
dl_tbf->update_ms(0x2342, GPRS_RLCMAC_DL_TBF);
|
2015-05-22 15:48:04 +00:00
|
|
|
dl_tbf->set_ta(4);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);
|
2020-05-08 16:15:59 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->ms() == ms);
|
2013-10-30 13:50:17 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(bts,
|
2020-05-08 16:15:59 +00:00
|
|
|
ms, 0, false);
|
2015-06-29 11:03:46 +00:00
|
|
|
OSMO_ASSERT(ul_tbf != NULL);
|
2015-05-21 14:58:22 +00:00
|
|
|
ul_tbf->update_ms(0x2342, GPRS_RLCMAC_UL_TBF);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2020-05-08 16:15:59 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ms() == ms);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
OSMO_ASSERT(bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI) == ms);
|
2013-10-30 13:50:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now check.. that DL changes and that the timing advance
|
|
|
|
* has changed.
|
|
|
|
*/
|
2015-05-21 14:58:22 +00:00
|
|
|
dl_tbf->update_ms(0x4232, GPRS_RLCMAC_DL_TBF);
|
2015-05-15 13:50:43 +00:00
|
|
|
|
|
|
|
/* It is still there, since the new TLLI has not been used for UL yet */
|
2021-01-14 15:48:38 +00:00
|
|
|
ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
|
2015-05-15 13:50:43 +00:00
|
|
|
OSMO_ASSERT(ms == ms_new);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms_new = bts_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
|
2015-05-15 13:50:43 +00:00
|
|
|
OSMO_ASSERT(ms == ms_new);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2013-10-30 13:50:17 +00:00
|
|
|
|
2015-05-15 13:50:43 +00:00
|
|
|
/* Now use the new TLLI for UL */
|
2015-05-21 14:58:22 +00:00
|
|
|
ul_tbf->update_ms(0x4232, GPRS_RLCMAC_UL_TBF);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI);
|
2015-05-15 13:50:43 +00:00
|
|
|
OSMO_ASSERT(ms_new == NULL);
|
2013-10-30 18:50:49 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms_new = bts_ms_by_tlli(bts, 0x4232, GSM_RESERVED_TMSI);
|
2015-05-22 15:48:04 +00:00
|
|
|
OSMO_ASSERT(ms_new != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms_new) == 4);
|
2015-05-22 15:48:04 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == 4);
|
|
|
|
OSMO_ASSERT(dl_tbf->ta() == 4);
|
|
|
|
|
|
|
|
ul_tbf->set_ta(6);
|
|
|
|
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == 6);
|
|
|
|
OSMO_ASSERT(dl_tbf->ta() == 6);
|
2016-01-11 15:12:01 +00:00
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2013-10-30 13:50:17 +00:00
|
|
|
}
|
|
|
|
|
2014-08-15 16:19:41 +00:00
|
|
|
static uint8_t llc_data[200];
|
|
|
|
|
2018-01-25 18:47:28 +00:00
|
|
|
/* override, requires '-Wl,--wrap=pcu_sock_send' */
|
|
|
|
int __real_pcu_sock_send(struct msgb *msg);
|
2021-01-18 16:54:30 +00:00
|
|
|
extern "C" int __wrap_pcu_sock_send(struct msgb *msg)
|
2014-08-15 16:19:41 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void setup_bts(struct gprs_rlcmac_bts *bts, uint8_t ts_no, uint8_t cs = 1)
|
2014-08-15 16:19:41 +00:00
|
|
|
{
|
|
|
|
gprs_rlcmac_trx *trx;
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2021-01-13 17:54:38 +00:00
|
|
|
the_pcu->alloc_algorithm = alloc_algorithm_a;
|
2015-06-02 14:00:41 +00:00
|
|
|
bts->initial_cs_dl = cs;
|
|
|
|
bts->initial_cs_ul = cs;
|
2021-01-14 11:01:42 +00:00
|
|
|
osmo_tdef_set(the_pcu->T_defs, -2030, 0, OSMO_TDEF_S);
|
|
|
|
osmo_tdef_set(the_pcu->T_defs, -2031, 0, OSMO_TDEF_S);
|
2014-08-15 16:19:41 +00:00
|
|
|
trx = &bts->trx[0];
|
|
|
|
|
|
|
|
trx->pdch[ts_no].enable();
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_set_current_frame_number(bts, DUMMY_FN);
|
2015-03-25 08:11:24 +00:00
|
|
|
}
|
2014-08-15 16:19:41 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_dl_tbf *create_dl_tbf(struct gprs_rlcmac_bts *bts, uint8_t ms_class,
|
2016-02-04 10:09:19 +00:00
|
|
|
uint8_t egprs_ms_class, uint8_t *trx_no_)
|
2015-03-25 08:11:24 +00:00
|
|
|
{
|
|
|
|
int tfi;
|
|
|
|
uint8_t trx_no;
|
2020-05-08 16:15:59 +00:00
|
|
|
GprsMs *ms;
|
2015-03-25 08:11:24 +00:00
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_alloc_ms(bts, ms_class, egprs_ms_class);
|
2015-03-25 08:11:24 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_DL_TBF, &trx_no, -1);
|
2014-08-15 16:19:41 +00:00
|
|
|
OSMO_ASSERT(tfi >= 0);
|
2020-05-08 16:15:59 +00:00
|
|
|
dl_tbf = tbf_alloc_dl_tbf(bts, ms, trx_no, true);
|
2020-10-26 13:52:06 +00:00
|
|
|
OSMO_ASSERT(dl_tbf);
|
2016-07-18 10:50:18 +00:00
|
|
|
dl_tbf->set_ta(0);
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(dl_tbf);
|
|
|
|
|
2014-08-15 16:19:41 +00:00
|
|
|
/* "Establish" the DL TBF */
|
2018-01-23 19:09:06 +00:00
|
|
|
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_SEND_ASS);
|
2018-01-12 14:48:12 +00:00
|
|
|
TBF_SET_STATE(dl_tbf, GPRS_RLCMAC_FLOW);
|
2014-08-15 16:19:41 +00:00
|
|
|
dl_tbf->m_wait_confirm = 0;
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(dl_tbf);
|
2014-08-15 16:19:41 +00:00
|
|
|
|
2015-03-25 08:11:24 +00:00
|
|
|
*trx_no_ = trx_no;
|
|
|
|
|
|
|
|
return dl_tbf;
|
|
|
|
}
|
|
|
|
|
2015-08-19 12:00:43 +00:00
|
|
|
static unsigned fn_add_blocks(unsigned fn, unsigned blocks)
|
|
|
|
{
|
|
|
|
unsigned bn = fn2bn(fn) + blocks;
|
|
|
|
fn = fn - (fn % 52);
|
|
|
|
fn += bn * 4 + bn / 3;
|
2017-05-16 14:10:45 +00:00
|
|
|
return fn % GSM_MAX_FN;
|
2015-08-19 12:00:43 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 10:00:33 +00:00
|
|
|
static void request_dl_rlc_block(struct gprs_rlcmac_bts *bts,
|
2016-07-20 11:05:05 +00:00
|
|
|
uint8_t trx_no, uint8_t ts_no,
|
2015-08-24 09:55:17 +00:00
|
|
|
uint32_t *fn, uint8_t *block_nr = NULL)
|
2015-03-25 09:05:34 +00:00
|
|
|
{
|
2015-08-24 09:55:17 +00:00
|
|
|
uint8_t bn = fn2bn(*fn);
|
2016-07-20 11:05:05 +00:00
|
|
|
gprs_rlcmac_rcv_rts_block(bts, trx_no, ts_no, *fn, bn);
|
2015-08-19 12:00:43 +00:00
|
|
|
*fn = fn_add_blocks(*fn, 1);
|
2015-08-24 09:55:17 +00:00
|
|
|
bn += 1;
|
|
|
|
if (block_nr)
|
|
|
|
*block_nr = bn;
|
2015-03-25 09:05:34 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 10:00:33 +00:00
|
|
|
static void request_dl_rlc_block(struct gprs_rlcmac_tbf *tbf,
|
2015-08-24 09:55:17 +00:00
|
|
|
uint32_t *fn, uint8_t *block_nr = NULL)
|
2015-08-24 09:34:47 +00:00
|
|
|
{
|
2021-01-14 15:48:38 +00:00
|
|
|
request_dl_rlc_block(tbf->bts, tbf->trx->trx_no,
|
2016-07-20 11:05:05 +00:00
|
|
|
tbf->control_ts, fn, block_nr);
|
2015-08-24 09:34:47 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 08:11:24 +00:00
|
|
|
enum test_tbf_final_ack_mode {
|
|
|
|
TEST_MODE_STANDARD,
|
|
|
|
TEST_MODE_REVERSE_FREE
|
|
|
|
};
|
|
|
|
|
|
|
|
static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-03-25 08:11:24 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
unsigned i;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
uint32_t fn;
|
2015-03-25 09:05:34 +00:00
|
|
|
uint8_t block_nr;
|
2015-03-25 08:11:24 +00:00
|
|
|
uint8_t trx_no;
|
2015-05-22 13:47:55 +00:00
|
|
|
GprsMs *ms;
|
2015-05-22 13:40:08 +00:00
|
|
|
uint32_t tlli = 0xffeeddcc;
|
2015-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
uint8_t rbb[64/8];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-01-11 15:12:01 +00:00
|
|
|
|
2015-03-25 08:11:24 +00:00
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
gprs_rlcmac_tbf *new_tbf;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
|
|
|
dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no);
|
2015-05-22 13:40:08 +00:00
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
2015-05-22 13:47:55 +00:00
|
|
|
ms = dl_tbf->ms();
|
2015-03-25 08:11:24 +00:00
|
|
|
|
2014-08-15 16:19:41 +00:00
|
|
|
for (i = 0; i < sizeof(llc_data); i++)
|
|
|
|
llc_data[i] = i%256;
|
|
|
|
|
2015-03-25 09:05:34 +00:00
|
|
|
/* Schedule two LLC frames */
|
2020-10-28 18:58:17 +00:00
|
|
|
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
|
|
|
|
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
|
2014-08-15 16:19:41 +00:00
|
|
|
|
|
|
|
|
2015-03-25 09:05:34 +00:00
|
|
|
/* Send only a few RLC/MAC blocks */
|
2014-08-15 16:19:41 +00:00
|
|
|
fn = 0;
|
2015-08-24 09:55:17 +00:00
|
|
|
do {
|
2014-08-15 16:19:41 +00:00
|
|
|
/* Request to send one block */
|
2015-08-24 10:00:33 +00:00
|
|
|
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
|
2015-08-24 09:55:17 +00:00
|
|
|
} while (block_nr < 3);
|
2015-08-24 09:34:47 +00:00
|
|
|
|
2015-03-25 09:05:34 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->have_data());
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
2014-08-15 16:19:41 +00:00
|
|
|
|
|
|
|
/* Queue a final ACK */
|
|
|
|
memset(rbb, 0, sizeof(rbb));
|
|
|
|
/* Receive a final ACK */
|
2017-12-15 10:14:30 +00:00
|
|
|
dl_tbf->rcvd_dl_ack(true, 1, rbb);
|
2014-08-15 16:19:41 +00:00
|
|
|
|
|
|
|
/* Clean up and ensure tbfs are in the correct state */
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
new_tbf = ms_dl_tbf(ms);
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(new_tbf);
|
2014-08-15 16:19:41 +00:00
|
|
|
OSMO_ASSERT(new_tbf != dl_tbf);
|
|
|
|
OSMO_ASSERT(new_tbf->tfi() == 1);
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(dl_tbf);
|
2018-01-23 19:09:06 +00:00
|
|
|
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
|
2015-02-23 13:26:59 +00:00
|
|
|
if (test_mode == TEST_MODE_REVERSE_FREE) {
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_ref(ms);
|
2015-02-23 13:26:59 +00:00
|
|
|
tbf_free(new_tbf);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) == NULL);
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(dl_tbf);
|
2015-02-23 13:26:59 +00:00
|
|
|
tbf_free(dl_tbf);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_unref(ms);
|
2015-02-23 13:26:59 +00:00
|
|
|
} else {
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_ref(ms);
|
2015-02-23 13:26:59 +00:00
|
|
|
tbf_free(dl_tbf);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) == new_tbf);
|
2015-02-23 14:10:20 +00:00
|
|
|
check_tbf(new_tbf);
|
2015-02-23 13:26:59 +00:00
|
|
|
tbf_free(new_tbf);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) == NULL);
|
|
|
|
ms_unref(ms);
|
2015-02-23 13:26:59 +00:00
|
|
|
}
|
2016-01-11 15:12:01 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2014-08-15 16:19:41 +00:00
|
|
|
}
|
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
/* Receive an ACK */
|
2020-10-23 19:00:23 +00:00
|
|
|
#define RCV_ACK(fin, tbf, rbb) do { \
|
|
|
|
gprs_rlc_dl_window *w = static_cast<gprs_rlc_dl_window *>(tbf->window()); \
|
|
|
|
tbf->rcvd_dl_ack(fin, w->v_s(), rbb); \
|
2017-12-15 10:25:14 +00:00
|
|
|
if (!fin) \
|
2020-10-23 19:00:23 +00:00
|
|
|
OSMO_ASSERT(w->window_empty()); \
|
2017-12-15 10:25:14 +00:00
|
|
|
} while(0)
|
|
|
|
|
2015-03-25 09:48:52 +00:00
|
|
|
static void test_tbf_delayed_release()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-03-25 09:48:52 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
unsigned i;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
uint32_t fn = 0;
|
|
|
|
uint8_t trx_no;
|
2015-05-22 13:40:08 +00:00
|
|
|
uint32_t tlli = 0xffeeddcc;
|
2019-09-09 11:41:00 +00:00
|
|
|
unsigned long dl_tbf_idle_msec;
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
uint8_t rbb[64/8];
|
|
|
|
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no);
|
2015-05-22 13:40:08 +00:00
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
for (i = 0; i < sizeof(llc_data); i++)
|
|
|
|
llc_data[i] = i%256;
|
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Schedule two LLC frames */
|
2020-10-28 18:58:17 +00:00
|
|
|
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
|
|
|
|
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Drain the queue */
|
|
|
|
while (dl_tbf->have_data())
|
|
|
|
/* Request to send one RLC/MAC block */
|
2015-08-24 10:00:33 +00:00
|
|
|
request_dl_rlc_block(dl_tbf, &fn);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* ACK all blocks */
|
|
|
|
memset(rbb, 0xff, sizeof(rbb));
|
2017-12-15 10:25:14 +00:00
|
|
|
|
|
|
|
RCV_ACK(false, dl_tbf, rbb); /* Receive an ACK */
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
/* Force sending of a single block containing an LLC dummy command */
|
2015-08-24 10:00:33 +00:00
|
|
|
request_dl_rlc_block(dl_tbf, &fn);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
RCV_ACK(false, dl_tbf, rbb); /* Receive an ACK */
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
/* Timeout (make sure fn % 52 remains valid) */
|
2021-01-14 11:01:42 +00:00
|
|
|
dl_tbf_idle_msec = osmo_tdef_get(the_pcu->T_defs, -2031, OSMO_TDEF_MS, -1);
|
2019-09-09 11:41:00 +00:00
|
|
|
fn += 52 * ((msecs_to_frames(dl_tbf_idle_msec + 100) + 51)/ 52);
|
2015-08-24 10:00:33 +00:00
|
|
|
request_dl_rlc_block(dl_tbf, &fn);
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FINISHED));
|
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
|
2015-03-25 09:48:52 +00:00
|
|
|
|
|
|
|
/* Clean up and ensure tbfs are in the correct state */
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
|
2018-01-23 19:09:06 +00:00
|
|
|
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
|
2015-03-25 09:48:52 +00:00
|
|
|
check_tbf(dl_tbf);
|
|
|
|
tbf_free(dl_tbf);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-03-25 09:48:52 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 09:07:16 +00:00
|
|
|
static void test_tbf_imsi()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-05-21 09:07:16 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
uint8_t trx_no;
|
|
|
|
GprsMs *ms1, *ms2;
|
|
|
|
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf[2];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf[0] = create_dl_tbf(bts, ms_class, 0, &trx_no);
|
|
|
|
dl_tbf[1] = create_dl_tbf(bts, ms_class, 0, &trx_no);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
|
|
|
dl_tbf[0]->update_ms(0xf1000001, GPRS_RLCMAC_DL_TBF);
|
|
|
|
dl_tbf[1]->update_ms(0xf1000002, GPRS_RLCMAC_DL_TBF);
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_imsi(dl_tbf[0]->ms(), "001001000000001");
|
2021-01-14 15:48:38 +00:00
|
|
|
ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000001");
|
2015-05-21 09:07:53 +00:00
|
|
|
OSMO_ASSERT(ms1 != NULL);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms2 = bts_ms_store(bts)->get_ms(0xf1000001);
|
2015-05-21 09:07:16 +00:00
|
|
|
OSMO_ASSERT(ms2 != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000001") == 0);
|
2015-05-21 09:07:53 +00:00
|
|
|
OSMO_ASSERT(ms1 == ms2);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
|
|
|
/* change the IMSI on TBF 0 */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_imsi(dl_tbf[0]->ms(), "001001000000002");
|
2021-01-14 15:48:38 +00:00
|
|
|
ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000001");
|
2015-05-21 09:07:16 +00:00
|
|
|
OSMO_ASSERT(ms1 == NULL);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
|
2015-05-21 09:07:53 +00:00
|
|
|
OSMO_ASSERT(ms1 != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000002") == 0);
|
2015-05-21 09:07:53 +00:00
|
|
|
OSMO_ASSERT(ms1 == ms2);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
2020-10-26 11:40:11 +00:00
|
|
|
/* use the same IMSI on TBF 1 */
|
2015-08-16 16:19:32 +00:00
|
|
|
{
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_ref(ms2);
|
|
|
|
ms_set_imsi(dl_tbf[1]->ms(), "001001000000002");
|
2021-01-14 15:48:38 +00:00
|
|
|
ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
|
2015-08-16 16:19:32 +00:00
|
|
|
OSMO_ASSERT(ms1 != NULL);
|
|
|
|
OSMO_ASSERT(ms1 != ms2);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(strcmp(ms_imsi(ms1), "001001000000002") == 0);
|
|
|
|
OSMO_ASSERT(strcmp(ms_imsi(ms2), "") == 0);
|
|
|
|
ms_unref(ms2);
|
2015-08-16 16:19:32 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms2 = bts_ms_store(bts)->get_ms(0xf1000001);
|
2015-08-16 16:19:32 +00:00
|
|
|
OSMO_ASSERT(ms2 == NULL);
|
2015-05-21 09:07:16 +00:00
|
|
|
|
|
|
|
tbf_free(dl_tbf[1]);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms1 = bts_ms_store(bts)->get_ms(0, 0, "001001000000002");
|
2015-05-21 09:07:16 +00:00
|
|
|
OSMO_ASSERT(ms1 == NULL);
|
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-05-21 09:07:16 +00:00
|
|
|
}
|
|
|
|
|
2015-04-09 17:17:21 +00:00
|
|
|
static void test_tbf_exhaustion()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-04-09 17:17:21 +00:00
|
|
|
unsigned i;
|
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
uint8_t buf[256] = {0};
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-04-09 17:17:21 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
|
|
|
|
if (!bts->pcu->nsi) {
|
2019-05-25 03:41:18 +00:00
|
|
|
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_init(bts, 1234, 1234, 1, 1, false, 0, 0, 0);
|
2015-04-09 17:17:21 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 1024; i++) {
|
|
|
|
uint32_t tlli = 0xc0000000 + i;
|
|
|
|
char imsi[16] = {0};
|
|
|
|
unsigned delay_csec = 1000;
|
|
|
|
|
2015-05-21 10:06:58 +00:00
|
|
|
snprintf(imsi, sizeof(imsi), "001001%09d", i);
|
2015-04-09 17:17:21 +00:00
|
|
|
|
2021-01-18 16:14:14 +00:00
|
|
|
rc = dl_tbf_handle(bts, tlli, 0, imsi, ms_class, 0,
|
2015-04-09 17:17:21 +00:00
|
|
|
delay_csec, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
OSMO_ASSERT(rc == -EBUSY);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-04-09 17:17:21 +00:00
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_destroy(bts);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2015-04-09 17:17:21 +00:00
|
|
|
}
|
|
|
|
|
2015-06-12 11:41:00 +00:00
|
|
|
static void test_tbf_dl_llc_loss()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-06-12 11:41:00 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
int rc = 0;
|
|
|
|
uint32_t tlli = 0xc0123456;
|
|
|
|
const char *imsi = "001001000123456";
|
|
|
|
unsigned delay_csec = 1000;
|
|
|
|
GprsMs *ms;
|
|
|
|
|
|
|
|
uint8_t buf[19];
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
|
|
|
|
if (!bts->pcu->nsi) {
|
2019-05-25 03:41:18 +00:00
|
|
|
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2019-09-09 11:19:06 +00:00
|
|
|
/* keep the MS object 10 seconds */
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2030, 10, OSMO_TDEF_S) == 0);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_init(bts, 2234, 2234, 1, 1, false, 0, 0, 0);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
|
|
|
/* Handle LLC frame 1 */
|
|
|
|
memset(buf, 1, sizeof(buf));
|
2021-01-18 16:14:14 +00:00
|
|
|
rc = dl_tbf_handle(bts, tlli, 0, imsi, ms_class, 0,
|
2015-06-12 11:41:00 +00:00
|
|
|
delay_csec, buf, sizeof(buf));
|
|
|
|
OSMO_ASSERT(rc >= 0);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_store(bts)->get_ms(0, 0, imsi);
|
2015-06-12 11:41:00 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
|
|
|
|
ms_dl_tbf(ms)->set_ta(0);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
|
|
|
/* Handle LLC frame 2 */
|
|
|
|
memset(buf, 2, sizeof(buf));
|
2021-01-18 16:14:14 +00:00
|
|
|
rc = dl_tbf_handle(bts, tlli, 0, imsi, ms_class, 0,
|
2015-06-12 11:41:00 +00:00
|
|
|
delay_csec, buf, sizeof(buf));
|
|
|
|
OSMO_ASSERT(rc >= 0);
|
|
|
|
|
|
|
|
/* TBF establishment fails (timeout) */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
tbf_free(ms_dl_tbf(ms));
|
2015-06-12 11:41:00 +00:00
|
|
|
|
|
|
|
/* Handle LLC frame 3 */
|
|
|
|
memset(buf, 3, sizeof(buf));
|
2021-01-18 16:14:14 +00:00
|
|
|
rc = dl_tbf_handle(bts, tlli, 0, imsi, ms_class, 0,
|
2015-06-12 11:41:00 +00:00
|
|
|
delay_csec, buf, sizeof(buf));
|
|
|
|
OSMO_ASSERT(rc >= 0);
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
|
|
|
/* Get first BSN */
|
|
|
|
struct msgb *msg;
|
|
|
|
int fn = 0;
|
|
|
|
uint8_t expected_data = 1;
|
2019-03-05 15:15:01 +00:00
|
|
|
static uint8_t exp[][GSM_MACBLOCK_LEN] = {
|
|
|
|
{ 0x07, 0x00, 0x00, 0x4d, 0x01, 0x01, 0x01,
|
|
|
|
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,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
|
|
|
|
};
|
2015-06-12 11:41:00 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
while (ms_dl_tbf(ms)->have_data()) {
|
|
|
|
msg = ms_dl_tbf(ms)->create_dl_acked_block(fn += 4, 7);
|
2015-06-12 11:41:00 +00:00
|
|
|
fprintf(stderr, "MSG = %s\n", msgb_hexdump(msg));
|
2019-03-05 15:15:01 +00:00
|
|
|
if (!msgb_eq_data_print(msg, exp[expected_data - 1], GSM_MACBLOCK_LEN))
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "%s failed at %u\n", __func__, expected_data);
|
2019-03-05 15:15:01 +00:00
|
|
|
|
2015-06-12 11:41:00 +00:00
|
|
|
expected_data += 1;
|
|
|
|
}
|
2015-06-12 12:06:09 +00:00
|
|
|
OSMO_ASSERT(expected_data-1 == 3);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-06-12 11:41:00 +00:00
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_destroy(bts);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2015-06-12 11:41:00 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_single_phase(struct gprs_rlcmac_bts *bts,
|
2015-08-19 12:00:43 +00:00
|
|
|
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta)
|
2015-05-27 11:03:15 +00:00
|
|
|
{
|
|
|
|
GprsMs *ms;
|
|
|
|
int tfi = 0;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
2015-08-19 12:00:43 +00:00
|
|
|
uint8_t trx_no = 0;
|
2015-05-27 11:03:15 +00:00
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x03, *fn, qta);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2015-05-27 11:03:15 +00:00
|
|
|
OSMO_ASSERT(ul_tbf != NULL);
|
|
|
|
|
2015-05-22 15:48:04 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
|
|
|
uint8_t data_msg[23] = {
|
|
|
|
0x00, /* GPRS_RLCMAC_DATA_BLOCK << 6 */
|
|
|
|
uint8_t(1 | (tfi << 2)),
|
|
|
|
uint8_t(1), /* BSN:7, E:1 */
|
2015-08-19 12:00:43 +00:00
|
|
|
uint8_t(tlli >> 24), uint8_t(tlli >> 16),
|
|
|
|
uint8_t(tlli >> 8), uint8_t(tlli), /* TLLI */
|
2015-05-27 11:03:15 +00:00
|
|
|
};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2015-08-19 12:00:43 +00:00
|
|
|
pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2015-05-27 11:03:15 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
|
|
|
|
2015-08-19 12:00:43 +00:00
|
|
|
return ul_tbf;
|
2015-05-27 11:03:15 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:18:12 +00:00
|
|
|
static void send_ul_mac_block_buf(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_pdch *pdch,
|
|
|
|
unsigned fn, uint8_t *buf, int num_bytes)
|
|
|
|
{
|
2021-03-17 14:26:37 +00:00
|
|
|
bts_set_current_block_frame_number(bts, fn);
|
2021-03-09 16:18:12 +00:00
|
|
|
pdch->rcv_block(buf, num_bytes, fn, &meas);
|
|
|
|
pdch_ulc_expire_fn(pdch->ulc, fn);
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void send_ul_mac_block(struct gprs_rlcmac_bts *bts, unsigned trx_no, unsigned ts_no,
|
2015-08-20 13:55:56 +00:00
|
|
|
RlcMacUplink_t *ulreq, unsigned fn)
|
|
|
|
{
|
|
|
|
bitvec *rlc_block;
|
|
|
|
uint8_t buf[64];
|
|
|
|
int num_bytes;
|
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
2017-02-04 02:10:08 +00:00
|
|
|
rlc_block = bitvec_alloc(23, tall_pcu_ctx);
|
2015-08-20 13:55:56 +00:00
|
|
|
|
2020-02-03 16:18:03 +00:00
|
|
|
OSMO_ASSERT(encode_gsm_rlcmac_uplink(rlc_block, ulreq) == 0);
|
2015-08-20 13:55:56 +00:00
|
|
|
num_bytes = bitvec_pack(rlc_block, &buf[0]);
|
|
|
|
OSMO_ASSERT(size_t(num_bytes) < sizeof(buf));
|
|
|
|
bitvec_free(rlc_block);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2021-03-09 16:18:12 +00:00
|
|
|
send_ul_mac_block_buf(bts, pdch, fn, &buf[0], num_bytes);
|
2015-08-20 13:55:56 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 17:01:13 +00:00
|
|
|
|
|
|
|
static uint32_t get_poll_fn(struct gprs_rlcmac_tbf *tbf, uint8_t poll_ts)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
for (node = rb_first(&ulc->tree_root); node; node = rb_next(node)) {
|
|
|
|
item = container_of(node, struct pdch_ulc_node, node);
|
|
|
|
if (item->type == PDCH_ULC_NODE_TBF_POLL && item->tbf_poll.poll_tbf == tbf)
|
|
|
|
return item->fn;
|
|
|
|
}
|
|
|
|
OSMO_ASSERT(0);
|
|
|
|
}
|
|
|
|
|
2015-08-21 13:03:23 +00:00
|
|
|
static void send_control_ack(gprs_rlcmac_tbf *tbf)
|
|
|
|
{
|
|
|
|
RlcMacUplink_t ulreq = {0};
|
|
|
|
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_CONTROL_ACK;
|
|
|
|
Packet_Control_Acknowledgement_t *ctrl_ack =
|
|
|
|
&ulreq.u.Packet_Control_Acknowledgement;
|
|
|
|
|
|
|
|
ctrl_ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ctrl_ack->TLLI = tbf->tlli();
|
2021-03-29 17:10:19 +00:00
|
|
|
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
|
|
|
|
&ulreq, get_poll_fn(tbf, tbf->control_ts));
|
2015-08-21 13:03:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:18:12 +00:00
|
|
|
static void send_empty_block(gprs_rlcmac_tbf *tbf, unsigned ts_no, 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);
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(struct gprs_rlcmac_bts *bts,
|
2016-08-25 11:07:30 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2016-08-25 11:07:30 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, this sends an Immediate
|
|
|
|
* Assignment Uplink on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x73, rach_fn, qta);
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
/* get next free TFI */
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
Count_MS_RA_capability_value = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Exist_Multislot_capability = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
Exist_GPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
GPRS_multislot_class = ms_class;
|
|
|
|
if (egprs_ms_class) {
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.Exist_EGPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-08-25 11:07:30 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.EGPRS_multislot_class = ms_class;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2016-08-25 11:07:30 +00:00
|
|
|
OSMO_ASSERT(ul_tbf);
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
|
|
|
|
|
|
|
/* send packet uplink assignment */
|
|
|
|
*fn = sba_fn;
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
/* send real acknowledgement */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
|
|
|
/* send fake data */
|
|
|
|
uint8_t data_msg[42] = {
|
|
|
|
0xf << 2, /* GPRS_RLCMAC_DATA_BLOCK << 6, CV = 15 */
|
2017-02-08 16:07:40 +00:00
|
|
|
(uint8_t)(tfi << 1),
|
2016-08-25 11:07:30 +00:00
|
|
|
1, /* BSN:7, E:1 */
|
|
|
|
};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2016-08-25 11:07:30 +00:00
|
|
|
pdch->rcv_block(&data_msg[0], 23, *fn, &meas);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2016-08-25 11:07:30 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 44.060, B.8.1
|
|
|
|
* first seg received first, later second seg
|
|
|
|
*/
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 0;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 1;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 0;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
struct msgb *msg1 = ul_tbf->create_ul_ack(*fn, ts_no);
|
|
|
|
|
2020-11-02 13:36:22 +00:00
|
|
|
static uint8_t exp1[] = { 0x40, 0x24, 0x01, 0x0b, 0x3e, 0x24, 0x46, 0x68, 0x90, 0x87, 0xb0, 0x06,
|
2019-03-05 15:15:01 +00:00
|
|
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!msgb_eq_data_print(msg1, exp1, GSM_MACBLOCK_LEN)) {
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "%s test failed on 1st segment!\n", __func__);
|
2019-03-05 15:15:01 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
egprs3->si = 0;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 4;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
msg1 = ul_tbf->create_ul_ack(*fn, ts_no);
|
|
|
|
|
2020-11-02 13:36:22 +00:00
|
|
|
static uint8_t exp2[] = { 0x40, 0x24, 0x01, 0x0b, 0x3e, 0x24, 0x46, 0x68, 0x90, 0x88, 0xb0, 0x06, 0x8b,
|
2019-03-05 15:15:01 +00:00
|
|
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
|
|
|
|
};
|
2016-08-25 11:07:30 +00:00
|
|
|
|
2019-03-05 15:15:01 +00:00
|
|
|
if (!msgb_eq_data_print(msg1, exp2, GSM_MACBLOCK_LEN)) {
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "%s test failed on 2nd segment!\n", __func__);
|
2019-03-05 15:15:01 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-25 11:07:30 +00:00
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(struct gprs_rlcmac_bts *bts,
|
2016-07-26 12:56:21 +00:00
|
|
|
uint8_t ts_no, 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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, this sends an Immediate
|
|
|
|
* Assignment Uplink on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x73, rach_fn, qta);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
/* get next free TFI */
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
Count_MS_RA_capability_value = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Exist_Multislot_capability = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
Exist_GPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
GPRS_multislot_class = ms_class;
|
|
|
|
if (egprs_ms_class) {
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.Exist_EGPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-07-26 12:56:21 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.EGPRS_multislot_class = ms_class;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2016-07-26 12:56:21 +00:00
|
|
|
OSMO_ASSERT(ul_tbf != NULL);
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
|
|
|
|
|
|
|
/* send packet uplink assignment */
|
|
|
|
*fn = sba_fn;
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
/* send real acknowledgement */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
|
|
|
|
|
|
|
/* send fake data */
|
|
|
|
uint8_t data_msg[42] = {
|
|
|
|
0x00 | 0xf << 2, /* GPRS_RLCMAC_DATA_BLOCK << 6, CV = 15 */
|
|
|
|
uint8_t(0 | (tfi << 1)),
|
|
|
|
uint8_t(1), /* BSN:7, E:1 */
|
|
|
|
};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2016-07-26 12:56:21 +00:00
|
|
|
pdch->rcv_block(&data_msg[0], 23, *fn, &meas);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2016-07-26 12:56:21 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 44.060, B.8.1
|
|
|
|
* first seg received first, later second seg
|
|
|
|
*/
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 1;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
struct gprs_rlc_data *block = ul_tbf->m_rlc.block(1);
|
|
|
|
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_FIRST_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 1;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 3;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
OSMO_ASSERT(block->cs_last ==
|
2019-03-06 16:04:59 +00:00
|
|
|
MCS6);
|
2016-07-26 12:56:21 +00:00
|
|
|
/* Assembled MCS is MCS6. so the size is 74 */
|
|
|
|
OSMO_ASSERT(block->len == 74);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 44.060, B.8.1
|
|
|
|
* second seg first, later first seg
|
|
|
|
*/
|
|
|
|
memset(data_msg, 0, sizeof(data_msg));
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 2;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 3;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(2);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_SECOND_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 2;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
OSMO_ASSERT(block->cs_last ==
|
2019-03-06 16:04:59 +00:00
|
|
|
MCS6);
|
2016-07-26 12:56:21 +00:00
|
|
|
/* Assembled MCS is MCS6. so the size is 74 */
|
|
|
|
OSMO_ASSERT(block->len == 74);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 44.060, B.8.1
|
|
|
|
* Error scenario with spb as 1
|
|
|
|
*/
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 3;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 1;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(3);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
/*
|
|
|
|
* TS 44.060, B.8.1
|
|
|
|
* comparison of rlc_data for multiple scenarios
|
|
|
|
* Receive First, the second(BSN 3)
|
|
|
|
* Receive First, First then Second(BSN 4)
|
|
|
|
* Receive Second then First(BSN 5)
|
|
|
|
* after above 3 scenarios are triggered,
|
|
|
|
* rlc_data of all 3 BSN are compared
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Initialize the data_msg */
|
|
|
|
for (i = 0; i < 42; i++)
|
|
|
|
data_msg[i] = i;
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 3;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(3);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_FIRST_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 3;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 3;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(3);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
/* Assembled MCS is MCS6. so the size is 74 */
|
|
|
|
OSMO_ASSERT(block->len == 74);
|
|
|
|
OSMO_ASSERT(block->cs_last ==
|
2019-03-06 16:04:59 +00:00
|
|
|
MCS6);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 4;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(4);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_FIRST_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 4;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(4);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_FIRST_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 4;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 3;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(4);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
OSMO_ASSERT(block->cs_last ==
|
2019-03-06 16:04:59 +00:00
|
|
|
MCS6);
|
2016-07-26 12:56:21 +00:00
|
|
|
/* Assembled MCS is MCS6. so the size is 74 */
|
|
|
|
OSMO_ASSERT(block->len == 74);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 5;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 3;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(5);
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_SECOND_SEG_RXD);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 1;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 5;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 2;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
|
|
|
|
pdch->rcv_block(data_msg, 42, *fn, &meas);
|
|
|
|
|
|
|
|
block = ul_tbf->m_rlc.block(5);
|
|
|
|
|
|
|
|
/* check the status of the block */
|
|
|
|
OSMO_ASSERT(block->spb_status.block_status_ul ==
|
|
|
|
EGPRS_RESEG_DEFAULT);
|
|
|
|
OSMO_ASSERT(block->cs_last ==
|
2019-03-06 16:04:59 +00:00
|
|
|
MCS6);
|
2016-07-26 12:56:21 +00:00
|
|
|
/* Assembled MCS is MCS6. so the size is 74 */
|
|
|
|
OSMO_ASSERT(block->len == 74);
|
|
|
|
|
|
|
|
OSMO_ASSERT(ul_tbf->m_rlc.block(5)->len ==
|
|
|
|
ul_tbf->m_rlc.block(4)->len);
|
|
|
|
OSMO_ASSERT(ul_tbf->m_rlc.block(5)->len ==
|
|
|
|
ul_tbf->m_rlc.block(3)->len);
|
|
|
|
|
|
|
|
/* Compare the spb status of each BSNs(3,4,5). should be same */
|
|
|
|
OSMO_ASSERT(
|
|
|
|
ul_tbf->m_rlc.block(5)->spb_status.block_status_ul ==
|
|
|
|
ul_tbf->m_rlc.block(4)->spb_status.block_status_ul);
|
|
|
|
OSMO_ASSERT(
|
|
|
|
ul_tbf->m_rlc.block(5)->spb_status.block_status_ul ==
|
|
|
|
ul_tbf->m_rlc.block(3)->spb_status.block_status_ul);
|
|
|
|
|
|
|
|
/* Compare the Assembled MCS of each BSNs(3,4,5). should be same */
|
|
|
|
OSMO_ASSERT(ul_tbf->m_rlc.block(5)->cs_last ==
|
|
|
|
ul_tbf->m_rlc.block(4)->cs_last);
|
|
|
|
OSMO_ASSERT(ul_tbf->m_rlc.block(5)->cs_last ==
|
|
|
|
ul_tbf->m_rlc.block(3)->cs_last);
|
|
|
|
|
|
|
|
/* Compare the data of each BSNs(3,4,5). should be same */
|
|
|
|
OSMO_ASSERT(
|
|
|
|
!memcmp(ul_tbf->m_rlc.block(5)->block,
|
|
|
|
ul_tbf->m_rlc.block(4)->block, ul_tbf->m_rlc.block(5)->len
|
|
|
|
));
|
|
|
|
OSMO_ASSERT(
|
|
|
|
!memcmp(ul_tbf->m_rlc.block(5)->block,
|
|
|
|
ul_tbf->m_rlc.block(3)->block, ul_tbf->m_rlc.block(5)->len
|
|
|
|
));
|
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf(struct gprs_rlcmac_bts *bts,
|
2017-01-24 10:23:35 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2017-01-24 10:23:35 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, this sends an Immediate
|
|
|
|
* Assignment Uplink on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x73, rach_fn, qta);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
/* get next free TFI */
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
Count_MS_RA_capability_value = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Exist_Multislot_capability = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
Exist_GPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
GPRS_multislot_class = ms_class;
|
|
|
|
if (egprs_ms_class) {
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.Exist_EGPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2017-01-24 10:23:35 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.
|
|
|
|
Multislot_capability.EGPRS_multislot_class = ms_class;
|
|
|
|
}
|
2021-01-14 15:48:38 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2017-01-24 10:23:35 +00:00
|
|
|
/* send packet uplink assignment */
|
|
|
|
*fn = sba_fn;
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
/* send real acknowledgement */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(struct gprs_rlcmac_bts *bts,
|
2017-01-24 10:23:35 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2017-01-24 10:23:35 +00:00
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
|
|
|
/* send fake data with cv=0*/
|
|
|
|
struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
|
|
|
|
uint8_t data[49] = {0};
|
|
|
|
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
|
|
|
|
/*header_construction */
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
/* Message with CRBB */
|
|
|
|
for (int i = 0 ; i < 80; i++) {
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 10;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = ((i * 2)&0x1f);
|
|
|
|
hdr3->bsn1_lo = ((i * 2)/32);
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x0;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
|
|
|
}
|
|
|
|
ul_tbf->create_ul_ack(*fn, ts_no);
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 0;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = 0;
|
|
|
|
hdr3->bsn1_lo = 2;
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x2b;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
|
|
|
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
2018-01-23 19:16:23 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ul_ack_state_is(GPRS_RLCMAC_UL_ACK_NONE));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2017-01-24 10:23:35 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(struct gprs_rlcmac_bts *bts,
|
2017-01-24 10:23:35 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2017-01-24 10:23:35 +00:00
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
|
|
|
/* send fake data with cv=0*/
|
|
|
|
struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
|
|
|
|
uint8_t data[49] = {0};
|
|
|
|
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
|
|
|
|
/*header_construction */
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
|
|
|
|
/* Message with URBB & URBB length */
|
|
|
|
for (int i = 0 ; i < 20; i++) {
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 10;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = ((i * 2)&0x1f);
|
|
|
|
hdr3->bsn1_lo = ((i * 2)/32);
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x0;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
|
|
|
}
|
|
|
|
ul_tbf->create_ul_ack(*fn, ts_no);
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 0;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = 0;
|
|
|
|
hdr3->bsn1_lo = 2;
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x2b;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
2020-05-15 14:57:48 +00:00
|
|
|
ul_tbf->create_ul_ack(*fn, ts_no);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
2018-01-23 19:16:23 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ul_ack_state_is(GPRS_RLCMAC_UL_ACK_NONE));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2017-01-24 10:23:35 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(struct gprs_rlcmac_bts *bts,
|
2017-01-24 10:23:35 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2017-01-24 10:23:35 +00:00
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2017-01-24 10:23:35 +00:00
|
|
|
OSMO_ASSERT(ul_tbf);
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
|
|
|
|
|
|
|
/* send fake data with cv=0*/
|
|
|
|
struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
|
|
|
|
uint8_t data[49] = {0};
|
|
|
|
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
|
|
|
|
/*header_construction */
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
|
|
|
|
/* Message with CRBB */
|
|
|
|
for (int i = 80 ; i < 160; i++) {
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 10;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = ((i)&0x1f);
|
|
|
|
hdr3->bsn1_lo = ((i)/32);
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x0;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
|
|
|
}
|
|
|
|
ul_tbf->create_ul_ack(*fn, ts_no);
|
|
|
|
memset(data, 0x2b, sizeof(data));
|
|
|
|
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
|
|
|
|
hdr3->r = 0;
|
|
|
|
hdr3->si = 0;
|
|
|
|
hdr3->cv = 0;
|
|
|
|
hdr3->tfi_hi = (tfi >> 3) & 0x3;
|
|
|
|
hdr3->tfi_lo = tfi & 0x7;
|
|
|
|
hdr3->bsn1_hi = 0;
|
|
|
|
hdr3->bsn1_lo = 2;
|
|
|
|
hdr3->cps_hi = 0;
|
|
|
|
hdr3->cps_lo = 0;
|
|
|
|
hdr3->spb = 0;
|
|
|
|
hdr3->rsb = 0;
|
|
|
|
hdr3->pi = 0;
|
|
|
|
hdr3->spare = 0;
|
|
|
|
hdr3->dummy = 1;
|
|
|
|
data[4] = 0x0;
|
|
|
|
data[5] = 0x2b;
|
|
|
|
data[6] = 0x2b;
|
|
|
|
data[7] = 0x2b;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2017-01-24 10:23:35 +00:00
|
|
|
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
|
|
|
|
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
2018-01-23 19:16:23 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ul_ack_state_is(GPRS_RLCMAC_UL_ACK_NONE));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2017-01-24 10:23:35 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(struct gprs_rlcmac_bts *bts,
|
2015-08-19 12:00:43 +00:00
|
|
|
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
uint8_t ms_class, uint8_t egprs_ms_class)
|
2015-05-27 11:03:15 +00:00
|
|
|
{
|
|
|
|
GprsMs *ms;
|
2015-08-19 12:00:43 +00:00
|
|
|
uint32_t rach_fn = *fn - 51;
|
|
|
|
uint32_t sba_fn = *fn + 52;
|
2015-05-27 11:03:15 +00:00
|
|
|
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 */
|
2016-07-20 11:05:05 +00:00
|
|
|
request_dl_rlc_block(bts, trx_no, ts_no, fn);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2016-08-17 09:47:21 +00:00
|
|
|
/* simulate RACH, sends an Immediate Assignment Uplink on the AGCH */
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x73, rach_fn, qta);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
|
|
|
/* get next free TFI */
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
|
|
|
|
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2015-08-21 16:00:54 +00:00
|
|
|
Count_MS_RA_capability_value = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2015-08-21 16:00:54 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2015-08-21 16:00:54 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
Exist_GPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2015-08-21 16:00:54 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
GPRS_multislot_class = ms_class;
|
2016-02-04 10:09:19 +00:00
|
|
|
if (egprs_ms_class) {
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-02-04 10:09:19 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
Exist_EGPRS_multislot_class = 1;
|
2020-03-23 17:49:16 +00:00
|
|
|
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability2.
|
2016-02-04 10:09:19 +00:00
|
|
|
MS_RA_capability_value[0].u.Content.Multislot_capability.
|
|
|
|
EGPRS_multislot_class = ms_class;
|
|
|
|
}
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2015-05-27 11:03:15 +00:00
|
|
|
OSMO_ASSERT(ul_tbf != NULL);
|
2015-05-22 15:48:04 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
|
|
|
/* send packet uplink assignment */
|
2015-08-19 12:00:43 +00:00
|
|
|
*fn = sba_fn;
|
2015-08-24 10:00:33 +00:00
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2015-08-21 13:03:23 +00:00
|
|
|
/* send real acknowledgement */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
2015-08-21 16:00:54 +00:00
|
|
|
check_tbf(ul_tbf);
|
|
|
|
|
2015-05-27 11:03:15 +00:00
|
|
|
/* send fake data */
|
|
|
|
uint8_t data_msg[23] = {
|
2015-08-21 16:00:54 +00:00
|
|
|
0x00 | 0xf << 2, /* GPRS_RLCMAC_DATA_BLOCK << 6, CV = 15 */
|
|
|
|
uint8_t(0 | (tfi << 1)),
|
2015-05-27 11:03:15 +00:00
|
|
|
uint8_t(1), /* BSN:7, E:1 */
|
|
|
|
};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2015-08-19 12:00:43 +00:00
|
|
|
pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas);
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2015-05-27 11:03:15 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void send_dl_data(struct gprs_rlcmac_bts *bts, uint32_t tlli, const char *imsi,
|
2015-08-21 16:00:54 +00:00
|
|
|
const uint8_t *data, unsigned data_size)
|
|
|
|
{
|
|
|
|
GprsMs *ms, *ms2;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_store(bts)->get_ms(tlli, 0, imsi);
|
2015-08-21 16:00:54 +00:00
|
|
|
|
2021-01-18 16:14:14 +00:00
|
|
|
dl_tbf_handle(bts, tlli, 0, imsi, 0, 0,
|
2015-08-21 16:00:54 +00:00
|
|
|
1000, data, data_size);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_imsi(bts, imsi);
|
2015-08-21 16:00:54 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms) != NULL);
|
2015-08-21 16:00:54 +00:00
|
|
|
|
|
|
|
if (imsi[0] && strcmp(imsi, "000") != 0) {
|
2021-01-14 15:48:38 +00:00
|
|
|
ms2 = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2015-08-21 16:00:54 +00:00
|
|
|
OSMO_ASSERT(ms == ms2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void transmit_dl_data(struct gprs_rlcmac_bts *bts, uint32_t tlli, uint32_t *fn,
|
2016-02-04 10:09:19 +00:00
|
|
|
uint8_t slots = 0xff)
|
2015-08-21 16:15:38 +00:00
|
|
|
{
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
GprsMs *ms;
|
|
|
|
unsigned ts_no;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
dl_tbf = ms_dl_tbf(ms);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(dl_tbf);
|
|
|
|
|
|
|
|
while (dl_tbf->have_data()) {
|
|
|
|
uint8_t bn = fn2bn(*fn);
|
2016-02-04 10:09:19 +00:00
|
|
|
for (ts_no = 0 ; ts_no < 8; ts_no += 1) {
|
|
|
|
if (!(slots & (1 << ts_no)))
|
|
|
|
continue;
|
2021-01-14 15:48:38 +00:00
|
|
|
gprs_rlcmac_rcv_rts_block(bts,
|
2016-07-20 11:05:05 +00:00
|
|
|
dl_tbf->trx->trx_no, ts_no,
|
2015-08-21 16:15:38 +00:00
|
|
|
*fn, bn);
|
2016-02-04 10:09:19 +00:00
|
|
|
}
|
2015-08-21 16:15:38 +00:00
|
|
|
*fn = fn_add_blocks(*fn, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
static inline void print_ta_tlli(const gprs_rlcmac_ul_tbf *ul_tbf, bool print_ms)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
|
|
|
|
if (print_ms)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms_tlli(ul_tbf->ms()), ms_ta(ul_tbf->ms()));
|
2018-02-01 15:49:23 +00:00
|
|
|
}
|
|
|
|
|
2015-08-19 12:00:43 +00:00
|
|
|
static void test_tbf_single_phase()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-19 12:00:43 +00:00
|
|
|
int ts_no = 7;
|
2016-11-07 12:07:36 +00:00
|
|
|
uint32_t fn = DUMMY_FN; /* 17,25,9 */
|
2015-08-19 12:00:43 +00:00
|
|
|
uint32_t tlli = 0xf1223344;
|
2015-08-21 16:00:54 +00:00
|
|
|
const char *imsi = "0011223344";
|
2015-08-19 12:00:43 +00:00
|
|
|
uint16_t qta = 31;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_single_phase(bts, ts_no, tlli, &fn, qta);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, (const uint8_t *)"TEST", 4);
|
2015-08-21 16:00:54 +00:00
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2015-08-19 12:00:43 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 10:23:35 +00:00
|
|
|
static void test_tbf_egprs_two_phase_puan(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2017-01-24 10:23:35 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
uint8_t egprs_ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
uint8_t test_data[256];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2017-01-24 10:23:35 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
|
|
|
bts->initial_mcs_dl = 9;
|
2021-01-14 13:30:03 +00:00
|
|
|
the_pcu->vty.ws_base = 128;
|
|
|
|
the_pcu->vty.ws_pdch = 64;
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf(bts, ts_no, tlli, &fn, qta, ms_class, egprs_ms_class);
|
2017-01-24 10:23:35 +00:00
|
|
|
/* Function to generate URBB with no length */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase_puan_URBB_no_length(bts, ts_no, tlli, &fn,
|
2017-01-24 10:23:35 +00:00
|
|
|
qta, ms_class, egprs_ms_class, ul_tbf);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2020-10-23 19:00:23 +00:00
|
|
|
static_cast<gprs_rlc_ul_window *>(ul_tbf->window())->reset_state();
|
2017-01-24 10:23:35 +00:00
|
|
|
/* Function to generate URBB with length */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase_puan_URBB_with_length(bts, ts_no, tlli, &fn,
|
2017-01-24 10:23:35 +00:00
|
|
|
qta, ms_class, egprs_ms_class, ul_tbf);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2020-10-23 19:00:23 +00:00
|
|
|
static_cast<gprs_rlc_ul_window *>(ul_tbf->window())->reset_state();
|
2017-01-24 10:23:35 +00:00
|
|
|
/* Function to generate CRBB */
|
2021-01-14 13:30:03 +00:00
|
|
|
the_pcu->vty.ws_base = 128;
|
|
|
|
the_pcu->vty.ws_pdch = 64;
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase_puan_CRBB(bts, ts_no, tlli, &fn,
|
2017-01-24 10:23:35 +00:00
|
|
|
qta, ms_class, egprs_ms_class);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2017-01-24 10:23:35 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2017-01-24 10:23:35 +00:00
|
|
|
}
|
2016-11-09 10:57:00 +00:00
|
|
|
/*
|
|
|
|
* Trigger rach for single block
|
|
|
|
*/
|
|
|
|
static void test_immediate_assign_rej_single_block()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-11-09 10:57:00 +00:00
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
int ts_no = 7;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->trx[0].pdch[ts_no].disable();
|
2016-11-09 10:57:00 +00:00
|
|
|
|
|
|
|
uint32_t rach_fn = fn - 51;
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, sends an Immediate Assignment
|
|
|
|
* Uplink reject on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
rc = bts_handle_rach(bts, 0x70, rach_fn, qta);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
Add new PDCH UL Controller, drop SBAllocator class
Right now we handle different types of UL allocations in different
classes like PollAllocator and SBAllocator, and they usually don't take
into account the other one in most cases. Furthermore, those objects are
usually per-BTS object, instead of per PDCH object.
This is a first step towards having a unified per-PDCH controller which
takes care of controlling what is scheduled and hence expected on the
uplink. Each PDCH has a UL Controller which keeps track of all reserved
uplink frame, be it SB, RRBP poll or USF assigned, all under the same
API.
As a first step, only the SBA part is fully implemented and used (being
it the easiest part to replace); TBF poll+usf will come in follow-up
patches later on. As a result, the SBAllocator per-BTS class dissappears
but some of its code is refactored/reused to provide more features to the
gprs_rlcmac_sba object, which is also further integrated into the new UL
Controller.
Related: OS#5020
Change-Id: I84b24beea4a1aa2c1528f41435f77bd16df2b947
2021-03-08 13:57:58 +00:00
|
|
|
OSMO_ASSERT(rc == -EBUSY);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-11-09 10:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trigger rach till resources(USF) exhaust
|
|
|
|
*/
|
|
|
|
static void test_immediate_assign_rej_multi_block()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-11-09 10:57:00 +00:00
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
int ts_no = 7;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
|
|
|
uint32_t rach_fn = fn - 51;
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, sends an Immediate Assignment Uplink
|
|
|
|
* reject on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
rc = bts_handle_rach(bts, 0x78, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x79, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7a, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7b, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7c, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7d, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7e, rach_fn, qta);
|
|
|
|
rc = bts_handle_rach(bts, 0x7f, rach_fn, qta);
|
2016-11-09 10:57:00 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(rc == -EBUSY);
|
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-11-09 10:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_immediate_assign_rej()
|
|
|
|
{
|
|
|
|
test_immediate_assign_rej_multi_block();
|
|
|
|
test_immediate_assign_rej_single_block();
|
|
|
|
}
|
|
|
|
|
2015-08-19 12:00:43 +00:00
|
|
|
static void test_tbf_two_phase()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-19 12:00:43 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
2015-08-21 16:00:54 +00:00
|
|
|
const char *imsi = "0011223344";
|
2015-08-19 12:00:43 +00:00
|
|
|
uint8_t ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-19 12:00:43 +00:00
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, (const uint8_t *)"TEST", 4);
|
2015-08-21 16:00:54 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-05-27 11:03:15 +00:00
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
static inline void print_ms(GprsMs *ms, bool old)
|
2018-02-01 15:49:23 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "%s MS: TLLI = 0x%08x, TA = %d, IMSI = %s, LLC = %zu\n",
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
old ? "Old" : "New", ms_tlli(ms), ms_ta(ms), ms_imsi(ms), llc_queue_size(ms_llc_queue(ms)));
|
2018-02-01 15:49:23 +00:00
|
|
|
}
|
|
|
|
|
2015-08-21 16:15:38 +00:00
|
|
|
static void test_tbf_ra_update_rach()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli1 = 0xf1223344;
|
|
|
|
uint32_t tlli2 = 0xf5667788;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
2021-03-09 16:18:12 +00:00
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
2015-08-21 16:15:38 +00:00
|
|
|
GprsMs *ms, *ms1, *ms2;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms1 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)"RAU_ACCEPT", 10);
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms1, true);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2015-08-21 13:03:23 +00:00
|
|
|
/* Send Packet Downlink Assignment to MS */
|
|
|
|
request_dl_rlc_block(ul_tbf, &fn);
|
|
|
|
|
|
|
|
/* Ack it */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
2015-08-21 16:15:38 +00:00
|
|
|
/* Make sure the RAU Accept gets sent to the MS */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 1);
|
2021-01-14 15:48:38 +00:00
|
|
|
transmit_dl_data(bts, tlli1, &fn);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-03-09 16:18:12 +00:00
|
|
|
dl_tbf = ms_dl_tbf(ms1);
|
|
|
|
OSMO_ASSERT(dl_tbf);
|
2021-03-29 17:10:19 +00:00
|
|
|
fn = get_poll_fn(dl_tbf, dl_tbf->control_ts);
|
|
|
|
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
|
2021-03-09 16:18:12 +00:00
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
|
2015-08-21 16:15:38 +00:00
|
|
|
/* Now establish a new TBF for the RA UPDATE COMPLETE (new TLLI) */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli2, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms2 = ul_tbf->ms();
|
|
|
|
|
|
|
|
/* The PCU cannot know yet, that both TBF belong to the same MS */
|
|
|
|
OSMO_ASSERT(ms1 != ms2);
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms1, true);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
/* Send some downlink data along with the new TLLI and the IMSI so that
|
|
|
|
* the PCU can see, that both MS objects belong to same MS */
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli2, imsi, (const uint8_t *)"DATA", 4);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_imsi(bts, imsi);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms == ms2);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms2, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms == NULL);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli2, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms == ms2);
|
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_tbf_dl_flow_and_rach_two_phase()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli1 = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
GprsMs *ms, *ms1, *ms2;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 1);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms1 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)"DATA 1 *************", 20);
|
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20);
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms1, true);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2);
|
|
|
|
dl_tbf = ms_dl_tbf(ms1);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(dl_tbf != NULL);
|
|
|
|
|
|
|
|
/* Get rid of old UL TBF */
|
|
|
|
tbf_free(ul_tbf);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms1 == ms);
|
|
|
|
|
|
|
|
/* Now establish a new UL TBF, this will consume one LLC packet */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms2 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms2, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
/* This should be the same MS object */
|
|
|
|
OSMO_ASSERT(ms2 == ms1);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms2 == ms);
|
|
|
|
|
2015-09-01 09:38:40 +00:00
|
|
|
/* A DL TBF should still exist */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms));
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
/* No queued packets should be lost */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void test_tbf_dl_flow_and_rach_single_phase()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli1 = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
GprsMs *ms, *ms1, *ms2;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 1);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms1 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)"DATA 1 *************", 20);
|
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20);
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms1, true);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2);
|
|
|
|
dl_tbf = ms_dl_tbf(ms1);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(dl_tbf != NULL);
|
|
|
|
|
|
|
|
/* Get rid of old UL TBF */
|
|
|
|
tbf_free(ul_tbf);
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms1 == ms);
|
|
|
|
|
|
|
|
/* Now establish a new UL TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_single_phase(bts, ts_no, tlli1, &fn, qta);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
ms2 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms2, false);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
/* There should be a different MS object */
|
|
|
|
OSMO_ASSERT(ms2 != ms1);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 16:15:38 +00:00
|
|
|
OSMO_ASSERT(ms2 == ms);
|
|
|
|
OSMO_ASSERT(ms1 != ms);
|
|
|
|
|
2016-01-21 19:48:39 +00:00
|
|
|
/* DL TBF should be removed */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(!ms_dl_tbf(ms));
|
2015-08-21 16:15:38 +00:00
|
|
|
|
|
|
|
/* No queued packets should be lost */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2);
|
2015-08-21 16:15:38 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-08-21 16:15:38 +00:00
|
|
|
}
|
|
|
|
|
2015-08-21 13:04:39 +00:00
|
|
|
static void test_tbf_dl_reuse()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2015-08-21 13:04:39 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli1 = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf1, *dl_tbf2;
|
|
|
|
GprsMs *ms1, *ms2;
|
|
|
|
unsigned i;
|
|
|
|
RlcMacUplink_t ulreq = {0};
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 1);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli1, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, 0);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
ms1 = ul_tbf->ms();
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, false);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
/* Send some LLC frames */
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
|
|
char buf[32];
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = snprintf(buf, sizeof(buf), "LLC PACKET %02i", i);
|
|
|
|
OSMO_ASSERT(rc > 0);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)buf, rc);
|
2015-08-21 13:04:39 +00:00
|
|
|
}
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ms(ms1, true);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
/* Send Packet Downlink Assignment to MS */
|
|
|
|
request_dl_rlc_block(ul_tbf, &fn);
|
|
|
|
|
|
|
|
/* Ack it */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
|
|
|
/* Transmit all data */
|
2021-01-14 15:48:38 +00:00
|
|
|
transmit_dl_data(bts, tlli1, &fn);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0);
|
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms1));
|
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms1)->state_is(GPRS_RLCMAC_FINISHED));
|
2015-08-21 13:04:39 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
dl_tbf1 = ms_dl_tbf(ms1);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
/* Send some LLC frames */
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
char buf[32];
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = snprintf(buf, sizeof(buf), "LLC PACKET %02i (TBF 2)", i);
|
|
|
|
OSMO_ASSERT(rc > 0);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli1, imsi, (const uint8_t *)buf, rc);
|
2015-08-21 13:04:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Fake Final DL Ack/Nack */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_DOWNLINK_ACK_NACK;
|
|
|
|
Packet_Downlink_Ack_Nack_t *ack = &ulreq.u.Packet_Downlink_Ack_Nack;
|
|
|
|
|
|
|
|
ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
ack->DOWNLINK_TFI = dl_tbf1->tfi();
|
|
|
|
ack->Ack_Nack_Description.FINAL_ACK_INDICATION = 1;
|
|
|
|
|
2021-03-29 17:10:19 +00:00
|
|
|
send_ul_mac_block(bts, 0, dl_tbf1->control_ts, &ulreq, get_poll_fn(dl_tbf1, dl_tbf1->control_ts));
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf1->state_is(GPRS_RLCMAC_WAIT_RELEASE));
|
|
|
|
|
|
|
|
request_dl_rlc_block(dl_tbf1, &fn);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms2 = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
|
2015-08-21 13:04:39 +00:00
|
|
|
OSMO_ASSERT(ms2 == ms1);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms2));
|
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_ASSIGN));
|
2015-08-21 13:04:39 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
dl_tbf2 = ms_dl_tbf(ms2);
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf1 != dl_tbf2);
|
|
|
|
|
|
|
|
send_control_ack(dl_tbf1);
|
2015-08-21 13:24:02 +00:00
|
|
|
OSMO_ASSERT(dl_tbf2->state_is(GPRS_RLCMAC_FLOW));
|
2015-08-21 13:04:39 +00:00
|
|
|
|
|
|
|
/* Transmit all data */
|
2021-01-14 15:48:38 +00:00
|
|
|
transmit_dl_data(bts, tlli1, &fn);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms2)) == 0);
|
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms2));
|
|
|
|
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_FINISHED));
|
2015-08-21 13:04:39 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2015-08-21 13:04:39 +00:00
|
|
|
}
|
|
|
|
|
2016-01-19 09:44:42 +00:00
|
|
|
static void test_tbf_gprs_egprs()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-01-19 09:44:42 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 45;
|
|
|
|
int rc = 0;
|
|
|
|
uint32_t tlli = 0xc0006789;
|
|
|
|
const char *imsi = "001001123456789";
|
|
|
|
unsigned delay_csec = 1000;
|
|
|
|
|
|
|
|
uint8_t buf[256] = {0};
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-01-19 09:44:42 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
|
|
|
|
if (!bts->pcu->nsi) {
|
2019-05-25 03:41:18 +00:00
|
|
|
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2016-01-19 09:44:42 +00:00
|
|
|
|
|
|
|
/* EGPRS-only */
|
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_init(bts, 3234, 3234, 1, 1, false, 0, 0, 0);
|
2016-01-19 09:44:42 +00:00
|
|
|
|
|
|
|
/* Does not support EGPRS */
|
2021-01-18 16:14:14 +00:00
|
|
|
rc = dl_tbf_handle(bts, tlli, 0, imsi, ms_class, 0,
|
2016-01-19 09:44:42 +00:00
|
|
|
delay_csec, buf, sizeof(buf));
|
|
|
|
|
2020-10-27 13:45:20 +00:00
|
|
|
OSMO_ASSERT(rc == 0);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-01-19 09:44:42 +00:00
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_destroy(bts);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2016-01-19 09:44:42 +00:00
|
|
|
}
|
2015-05-27 11:03:15 +00:00
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
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)
|
|
|
|
{
|
2021-01-14 15:48:38 +00:00
|
|
|
gprs_rlcmac_bts *bts = dl_tbf->bts;
|
2018-02-01 15:49:23 +00:00
|
|
|
if (!dl_tbf) {
|
|
|
|
fprintf(stderr, "%s(): FAILED (NULL TBF)\n", test);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "DL TBF slots: 0x%02x, N: %d, WS: %d",
|
|
|
|
dl_tbf->dl_slots(),
|
|
|
|
pcu_bitcount(dl_tbf->dl_slots()),
|
|
|
|
dl_tbf->window_size());
|
|
|
|
|
|
|
|
if (pcu_bitcount(dl_tbf->dl_slots()) != exp_slots || dl_tbf->window_size() != exp_ws)
|
|
|
|
fprintf(stderr, "%s(): DL TBF FAILED: dl_slots = %u (exp. %u), WS = %u (exp. %u)",
|
|
|
|
test, pcu_bitcount(dl_tbf->dl_slots()), 4, dl_tbf->window_size(), 128 + 4 * 64);
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
if (free)
|
|
|
|
tbf_free(dl_tbf);
|
|
|
|
|
|
|
|
if (end) {
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", test);
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_destroy(bts);
|
2018-02-01 15:49:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:53:30 +00:00
|
|
|
static void test_tbf_ws()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2020-05-08 16:15:59 +00:00
|
|
|
GprsMs *ms;
|
2016-01-19 14:53:30 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 12;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-01-19 14:53:30 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
|
|
|
|
if (!bts->pcu->nsi) {
|
2019-05-25 03:41:18 +00:00
|
|
|
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2016-01-19 14:53:30 +00:00
|
|
|
|
2021-01-14 13:30:03 +00:00
|
|
|
the_pcu->vty.ws_base = 128;
|
|
|
|
the_pcu->vty.ws_pdch = 64;
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2021-01-13 17:54:38 +00:00
|
|
|
the_pcu->alloc_algorithm = alloc_algorithm_b;
|
2016-01-19 14:53:30 +00:00
|
|
|
bts->trx[0].pdch[2].enable();
|
|
|
|
bts->trx[0].pdch[3].enable();
|
|
|
|
bts->trx[0].pdch[4].enable();
|
|
|
|
bts->trx[0].pdch[5].enable();
|
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_init(bts, 4234, 4234, 1, 1, false, 0, 0, 0);
|
2016-01-19 14:53:30 +00:00
|
|
|
|
|
|
|
/* Does no support EGPRS */
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_alloc_ms(bts, ms_class, 0);
|
2020-05-08 16:15:59 +00:00
|
|
|
dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, false);
|
2018-02-01 15:49:23 +00:00
|
|
|
|
|
|
|
ws_check(dl_tbf, __func__, 4, 64, true, false);
|
2016-01-19 14:53:30 +00:00
|
|
|
|
|
|
|
/* EGPRS-only */
|
|
|
|
|
|
|
|
/* Does support EGPRS */
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_alloc_ms(bts, ms_class, ms_class);
|
2020-05-08 16:15:59 +00:00
|
|
|
dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, false);
|
2016-01-19 14:53:30 +00:00
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true, true);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2016-01-19 14:53:30 +00:00
|
|
|
}
|
|
|
|
|
2016-08-30 10:09:04 +00:00
|
|
|
static void test_tbf_update_ws(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2020-05-08 16:15:59 +00:00
|
|
|
GprsMs *ms;
|
2016-08-30 10:09:04 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
uint8_t ms_class = 11;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-08-30 10:09:04 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
|
|
|
|
if (!bts->pcu->nsi) {
|
2019-05-25 03:41:18 +00:00
|
|
|
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2016-08-30 10:09:04 +00:00
|
|
|
|
2021-01-14 13:30:03 +00:00
|
|
|
the_pcu->vty.ws_base = 128;
|
|
|
|
the_pcu->vty.ws_pdch = 64;
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2021-01-13 17:54:38 +00:00
|
|
|
the_pcu->alloc_algorithm = alloc_algorithm_b;
|
2016-08-30 10:09:04 +00:00
|
|
|
bts->trx[0].pdch[2].enable();
|
|
|
|
bts->trx[0].pdch[3].enable();
|
|
|
|
bts->trx[0].pdch[4].enable();
|
|
|
|
bts->trx[0].pdch[5].enable();
|
|
|
|
|
2020-09-16 19:52:02 +00:00
|
|
|
gprs_bssgp_init(bts, 5234, 5234, 1, 1, false, 0, 0, 0);
|
2016-08-30 10:09:04 +00:00
|
|
|
|
|
|
|
/* EGPRS-only */
|
|
|
|
|
|
|
|
/* Does support EGPRS */
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_alloc_ms(bts, ms_class, ms_class);
|
2020-05-08 16:15:59 +00:00
|
|
|
dl_tbf = tbf_alloc_dl_tbf(bts, ms, 0, true);
|
2016-08-30 10:09:04 +00:00
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
ws_check(dl_tbf, __func__, 1, 128 + 1 * 64, false, false);
|
2016-08-30 10:09:04 +00:00
|
|
|
|
|
|
|
dl_tbf->update();
|
|
|
|
|
2016-09-15 12:24:46 +00:00
|
|
|
/* window size should be 384 */
|
2018-02-01 15:49:23 +00:00
|
|
|
ws_check(dl_tbf, __func__, 4, 128 + 4 * 64, true, true);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2016-08-30 10:09:04 +00:00
|
|
|
}
|
|
|
|
|
2016-08-25 11:07:30 +00:00
|
|
|
static void test_tbf_puan_urbb_len(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-08-25 11:07:30 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
uint8_t egprs_ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
uint8_t test_data[256];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-08-25 11:07:30 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
|
|
|
bts->initial_mcs_dl = 9;
|
2016-08-25 11:07:30 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = puan_urbb_len_issue(bts, ts_no, tlli, &fn, qta,
|
2016-08-25 11:07:30 +00:00
|
|
|
ms_class, egprs_ms_class);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2016-08-25 11:07:30 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-08-25 11:07:30 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_ul_tbf *tbf_li_decoding(struct gprs_rlcmac_bts *bts,
|
2016-09-15 11:49:54 +00:00
|
|
|
uint8_t ts_no, 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;
|
2017-02-08 16:07:40 +00:00
|
|
|
int tfi = 0;
|
2016-09-15 11:49:54 +00:00
|
|
|
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;
|
|
|
|
MS_Radio_Access_capability_t *pmsradiocap = NULL;
|
|
|
|
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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* simulate RACH, this sends an Immediate
|
|
|
|
* Assignment Uplink on the AGCH
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
bts_handle_rach(bts, 0x73, rach_fn, qta);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
/* get next free TFI */
|
2021-01-14 15:48:38 +00:00
|
|
|
tfi = bts_tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx_no, -1);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
presreq = &ulreq.u.Packet_Resource_Request;
|
|
|
|
presreq->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
presreq->ID.UnionType = 1; /* != 0 */
|
|
|
|
presreq->ID.u.TLLI = tlli;
|
2020-03-23 17:49:16 +00:00
|
|
|
presreq->Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
pmsradiocap = &presreq->MS_Radio_Access_capability2;
|
2016-09-15 11:49:54 +00:00
|
|
|
pmsradiocap->Count_MS_RA_capability_value = 1;
|
|
|
|
pmsradiocap->MS_RA_capability_value[0].u.Content.
|
|
|
|
Exist_Multislot_capability = 1;
|
|
|
|
pmultislotcap = &pmsradiocap->MS_RA_capability_value[0].
|
|
|
|
u.Content.Multislot_capability;
|
|
|
|
|
|
|
|
pmultislotcap->Exist_GPRS_multislot_class = 1;
|
|
|
|
pmultislotcap->GPRS_multislot_class = ms_class;
|
|
|
|
if (egprs_ms_class) {
|
|
|
|
pmultislotcap->Exist_EGPRS_multislot_class = 1;
|
|
|
|
pmultislotcap->EGPRS_multislot_class = ms_class;
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
/* check the TBF */
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = bts_ul_tbf_by_tfi(bts, tfi, trx_no, ts_no);
|
2016-09-15 11:49:54 +00:00
|
|
|
OSMO_ASSERT(ul_tbf);
|
|
|
|
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
|
|
|
|
|
|
|
|
/* send packet uplink assignment */
|
|
|
|
*fn = sba_fn;
|
|
|
|
request_dl_rlc_block(ul_tbf, fn);
|
|
|
|
|
|
|
|
/* send real acknowledgement */
|
|
|
|
send_control_ack(ul_tbf);
|
|
|
|
|
|
|
|
check_tbf(ul_tbf);
|
|
|
|
|
|
|
|
uint8_t data_msg[49] = {0};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
pdch = &bts->trx[trx_no].pdch[ts_no];
|
2016-09-15 11:49:54 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
2016-09-15 11:49:54 +00:00
|
|
|
OSMO_ASSERT(ms != NULL);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms_ta(ms) == qta/4);
|
|
|
|
OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
|
|
|
|
egprs3->si = 0;
|
|
|
|
egprs3->r = 1;
|
|
|
|
egprs3->cv = 7;
|
|
|
|
egprs3->tfi_hi = tfi & 0x03;
|
|
|
|
egprs3->tfi_lo = (tfi & 0x1c) >> 2;
|
|
|
|
egprs3->bsn1_hi = 0;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
egprs3->cps_hi = 1;
|
|
|
|
data_msg[3] = 0xff;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 0;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
pdch->rcv_block(data_msg, 49, *fn, &meas);
|
|
|
|
|
|
|
|
egprs3->bsn1_hi = 1;
|
|
|
|
egprs3->bsn1_lo = 0;
|
|
|
|
data_msg[3] = 0x7f;
|
|
|
|
egprs3->cps_lo = 1;
|
|
|
|
egprs3->rsb = 0;
|
|
|
|
egprs3->spb = 0;
|
|
|
|
egprs3->pi = 0;
|
|
|
|
data_msg[4] = 0x2;
|
|
|
|
data_msg[5] = 0x0;
|
|
|
|
pdch->rcv_block(data_msg, 49, *fn, &meas);
|
|
|
|
|
2016-09-15 11:54:49 +00:00
|
|
|
OSMO_ASSERT(ul_tbf->m_llc.m_index == 43);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
return ul_tbf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_tbf_li_decoding(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-09-15 11:49:54 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
uint8_t egprs_ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
uint8_t test_data[256];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-09-15 11:49:54 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
|
|
|
bts->initial_mcs_dl = 9;
|
2016-09-15 11:49:54 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = tbf_li_decoding(bts, ts_no, tlli, &fn, qta,
|
2016-09-15 11:49:54 +00:00
|
|
|
ms_class, egprs_ms_class);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2016-09-15 11:49:54 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-09-15 11:49:54 +00:00
|
|
|
}
|
|
|
|
|
2016-10-25 07:15:24 +00:00
|
|
|
/*
|
|
|
|
* Test that a bit within the uncompressed bitmap whose BSN is not within
|
|
|
|
* the transmit window shall be ignored. See section 9.1.8.2.4 of 44.060
|
|
|
|
* version 7.27.0 Release 7.
|
|
|
|
*/
|
|
|
|
static void test_tbf_epdan_out_of_rx_window(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-10-25 07:15:24 +00:00
|
|
|
uint8_t ms_class = 11;
|
|
|
|
uint8_t egprs_ms_class = 11;
|
|
|
|
uint8_t trx_no;
|
|
|
|
uint32_t tlli = 0xffeeddcc;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
int ts_no = 4;
|
|
|
|
bitvec *block;
|
|
|
|
uint8_t bits_data[RLC_EGPRS_MAX_WS/8];
|
|
|
|
bitvec bits;
|
|
|
|
int bsn_begin, bsn_end;
|
|
|
|
EGPRS_PD_AckNack_t *ack_nack;
|
|
|
|
RlcMacUplink_t ul_control_block;
|
|
|
|
gprs_rlc_v_b *prlcmvb;
|
|
|
|
gprs_rlc_dl_window *prlcdlwindow;
|
2020-02-03 16:18:03 +00:00
|
|
|
int rc;
|
2016-10-25 07:15:24 +00:00
|
|
|
|
2016-12-09 10:42:42 +00:00
|
|
|
memset(&ul_control_block, 0, sizeof(RlcMacUplink_t));
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-10-25 07:15:24 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
|
2016-10-25 07:15:24 +00:00
|
|
|
/* ARQ II */
|
2021-01-14 12:08:02 +00:00
|
|
|
the_pcu->vty.dl_arq_type = EGPRS_ARQ2;
|
2016-10-25 07:15:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Simulate a message captured during over-the-air testing,
|
|
|
|
* where the following values were observed:
|
|
|
|
* v_a = 1176, vs = 1288, max sns = 2048, window size = 480.
|
|
|
|
*/
|
|
|
|
uint8_t data_msg[23] = {0x40, 0x20, 0x0b, 0xff, 0xd1,
|
|
|
|
0x61, 0x00, 0x3e, 0x0e, 0x51, 0x9f,
|
|
|
|
0xff, 0xff, 0xfb, 0x80, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
|
2016-10-25 07:15:24 +00:00
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
2020-10-23 19:00:23 +00:00
|
|
|
prlcdlwindow = static_cast<gprs_rlc_dl_window *>(dl_tbf->window());
|
2016-10-25 07:15:24 +00:00
|
|
|
prlcmvb = &prlcdlwindow->m_v_b;
|
|
|
|
prlcdlwindow->m_v_s = 1288;
|
|
|
|
prlcdlwindow->m_v_a = 1176;
|
|
|
|
prlcdlwindow->set_sns(2048);
|
|
|
|
prlcdlwindow->set_ws(480);
|
|
|
|
prlcmvb->mark_unacked(1176);
|
|
|
|
prlcmvb->mark_unacked(1177);
|
|
|
|
prlcmvb->mark_unacked(1286);
|
|
|
|
prlcmvb->mark_unacked(1287);
|
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
2017-02-04 02:10:08 +00:00
|
|
|
block = bitvec_alloc(23, tall_pcu_ctx);
|
2016-10-25 07:15:24 +00:00
|
|
|
|
|
|
|
bitvec_unpack(block, data_msg);
|
|
|
|
|
|
|
|
bits.data = bits_data;
|
|
|
|
bits.data_len = sizeof(bits_data);
|
|
|
|
bits.cur_bit = 0;
|
|
|
|
|
2020-02-03 16:18:03 +00:00
|
|
|
rc = decode_gsm_rlcmac_uplink(block, &ul_control_block);
|
|
|
|
OSMO_ASSERT(rc == 0);
|
2016-10-25 07:15:24 +00:00
|
|
|
|
|
|
|
ack_nack = &ul_control_block.u.Egprs_Packet_Downlink_Ack_Nack;
|
|
|
|
|
|
|
|
OSMO_ASSERT(prlcmvb->is_unacked(1176));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_unacked(1177));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_unacked(1286));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_unacked(1287));
|
|
|
|
|
|
|
|
Decoding::decode_egprs_acknack_bits(
|
|
|
|
&ack_nack->EGPRS_AckNack.Desc, &bits,
|
2020-10-23 19:00:23 +00:00
|
|
|
&bsn_begin, &bsn_end, prlcdlwindow);
|
2016-10-25 07:15:24 +00:00
|
|
|
|
|
|
|
dl_tbf->rcvd_dl_ack(
|
|
|
|
ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
|
|
|
|
bsn_begin, &bits);
|
|
|
|
|
2016-11-02 10:18:00 +00:00
|
|
|
OSMO_ASSERT(prlcmvb->is_invalid(1176));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_invalid(1177));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_acked(1286));
|
|
|
|
OSMO_ASSERT(prlcmvb->is_acked(1287));
|
2016-10-25 07:15:24 +00:00
|
|
|
|
|
|
|
bitvec_free(block);
|
|
|
|
tbf_free(dl_tbf);
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-10-25 07:15:24 +00:00
|
|
|
}
|
|
|
|
|
2016-07-26 12:56:21 +00:00
|
|
|
static void test_tbf_egprs_two_phase_spb(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-07-26 12:56:21 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
uint8_t egprs_ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
uint8_t test_data[256];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-07-26 12:56:21 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
|
|
|
bts->initial_mcs_dl = 9;
|
2016-07-26 12:56:21 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase_spb(bts, ts_no, tlli, &fn, qta,
|
2016-07-26 12:56:21 +00:00
|
|
|
ms_class, egprs_ms_class);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2016-07-26 12:56:21 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-07-26 12:56:21 +00:00
|
|
|
}
|
|
|
|
|
2016-02-04 10:09:19 +00:00
|
|
|
static void test_tbf_egprs_two_phase()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-02-04 10:09:19 +00:00
|
|
|
int ts_no = 7;
|
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
uint32_t tlli = 0xf1223344;
|
|
|
|
const char *imsi = "0011223344";
|
|
|
|
uint8_t ms_class = 1;
|
|
|
|
uint8_t egprs_ms_class = 1;
|
|
|
|
gprs_rlcmac_ul_tbf *ul_tbf;
|
|
|
|
uint8_t test_data[256];
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
|
|
|
bts->initial_mcs_dl = 9;
|
2016-02-04 10:09:19 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = establish_ul_tbf_two_phase(bts, ts_no, tlli, &fn, qta,
|
2016-02-04 10:09:19 +00:00
|
|
|
ms_class, egprs_ms_class);
|
|
|
|
|
2018-02-01 15:49:23 +00:00
|
|
|
print_ta_tlli(ul_tbf, true);
|
2021-01-14 15:48:38 +00:00
|
|
|
send_dl_data(bts, tlli, imsi, test_data, sizeof(test_data));
|
2016-02-04 10:09:19 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-02-04 10:09:19 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
|
2016-02-04 10:09:19 +00:00
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
uint8_t ms_class = 11;
|
|
|
|
uint8_t egprs_ms_class = 11;
|
|
|
|
uint32_t fn = 0;
|
|
|
|
uint8_t trx_no;
|
|
|
|
uint32_t tlli = 0xffeeddcc;
|
|
|
|
uint8_t test_data[512];
|
|
|
|
|
|
|
|
uint8_t rbb[64/8];
|
|
|
|
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "Testing MCS-%d\n", mcs);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->initial_mcs_dl = mcs;
|
2016-02-04 10:09:19 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
|
2016-02-04 10:09:19 +00:00
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(llc_data); i++)
|
|
|
|
llc_data[i] = i%256;
|
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Schedule a small LLC frame */
|
2020-10-28 18:58:17 +00:00
|
|
|
dl_tbf->append_data(1000, test_data, 10);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Drain the queue */
|
2021-03-09 16:18:12 +00:00
|
|
|
while (dl_tbf->have_data()) {
|
2016-02-04 10:09:19 +00:00
|
|
|
/* Request to send one RLC/MAC block */
|
|
|
|
request_dl_rlc_block(dl_tbf, &fn);
|
2021-03-09 16:18:12 +00:00
|
|
|
}
|
2021-03-29 17:10:19 +00:00
|
|
|
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
/* Schedule a large LLC frame */
|
2020-10-28 18:58:17 +00:00
|
|
|
dl_tbf->append_data(1000, test_data, sizeof(test_data));
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Drain the queue */
|
2021-03-09 16:18:12 +00:00
|
|
|
while (dl_tbf->have_data()) {
|
2016-02-04 10:09:19 +00:00
|
|
|
/* Request to send one RLC/MAC block */
|
|
|
|
request_dl_rlc_block(dl_tbf, &fn);
|
2021-03-09 16:18:12 +00:00
|
|
|
}
|
2021-03-29 17:10:19 +00:00
|
|
|
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
/* Clean up and ensure tbfs are in the correct state */
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
|
2018-01-23 19:09:06 +00:00
|
|
|
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
|
2016-02-04 10:09:19 +00:00
|
|
|
check_tbf(dl_tbf);
|
|
|
|
tbf_free(dl_tbf);
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
|
2016-07-12 10:20:29 +00:00
|
|
|
int mcs)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
uint8_t ms_class = 11;
|
|
|
|
uint8_t egprs_ms_class = 11;
|
|
|
|
uint8_t trx_no;
|
|
|
|
uint32_t tlli = 0xffeeddcc;
|
|
|
|
uint8_t test_data[512];
|
|
|
|
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
|
|
|
|
memset(test_data, 1, sizeof(test_data));
|
2021-01-14 15:48:38 +00:00
|
|
|
bts->initial_mcs_dl = mcs;
|
2016-07-12 10:20:29 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no);
|
2016-07-12 10:20:29 +00:00
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(test_data); i++)
|
|
|
|
test_data[i] = i%256;
|
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
/* Schedule a LLC frame
|
|
|
|
* passing only 100 bytes, since it is enough to construct
|
|
|
|
* 2 RLC data blocks. Which are enough to test Header Type 1
|
|
|
|
* cases
|
|
|
|
*/
|
2020-10-28 18:58:17 +00:00
|
|
|
dl_tbf->append_data(1000, test_data, 100);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
|
|
|
|
|
|
|
|
return dl_tbf;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf)
|
|
|
|
{
|
|
|
|
uint8_t rbb[64/8];
|
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
/* Clean up and ensure tbfs are in the correct state */
|
|
|
|
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
|
2018-01-23 19:09:06 +00:00
|
|
|
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
|
2016-07-12 10:20:29 +00:00
|
|
|
check_tbf(dl_tbf);
|
|
|
|
tbf_free(dl_tbf);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
#define NACK(tbf, x) do { \
|
2020-10-23 19:00:23 +00:00
|
|
|
gprs_rlc_dl_window *w = static_cast<gprs_rlc_dl_window *>(tbf->window()); \
|
|
|
|
w->m_v_b.mark_nacked(x); \
|
|
|
|
OSMO_ASSERT(w->m_v_b.is_nacked(x)); \
|
2017-12-15 10:25:14 +00:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define CHECK_UNACKED(tbf, cs, bsn) do { \
|
2020-10-23 19:00:23 +00:00
|
|
|
gprs_rlc_dl_window *w = static_cast<gprs_rlc_dl_window *>(tbf->window()); \
|
|
|
|
OSMO_ASSERT(w->m_v_b.is_unacked(bsn)); \
|
2019-03-12 14:50:57 +00:00
|
|
|
OSMO_ASSERT(mcs_chan_code(tbf->m_rlc.block(bsn)->cs_current_trans) == cs - 1); \
|
2017-12-15 10:25:14 +00:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define CHECK_NACKED(tbf, cs, bsn) do { \
|
2020-10-23 19:00:23 +00:00
|
|
|
gprs_rlc_dl_window *w = static_cast<gprs_rlc_dl_window *>(tbf->window()); \
|
|
|
|
OSMO_ASSERT(w->m_v_b.is_nacked(bsn)); \
|
2019-03-12 14:50:57 +00:00
|
|
|
OSMO_ASSERT(mcs_chan_code(tbf->m_rlc.block(bsn)->cs_current_trans) == cs - 1); \
|
2017-12-15 10:25:14 +00:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define MAKE_ACKED(m, tbf, fn, cs, check_unacked) do { \
|
|
|
|
m = tbf->create_dl_acked_block(fn, tbf->control_ts); \
|
|
|
|
OSMO_ASSERT(m); \
|
|
|
|
if (check_unacked) \
|
|
|
|
CHECK_UNACKED(tbf, cs, 0); \
|
|
|
|
else \
|
|
|
|
CHECK_NACKED(tbf, cs, 0); \
|
|
|
|
} while(0)
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void egprs_spb_to_normal_validation(struct gprs_rlcmac_bts *bts,
|
2017-02-08 16:07:40 +00:00
|
|
|
unsigned int mcs, unsigned int demanded_mcs)
|
2016-08-22 11:51:10 +00:00
|
|
|
{
|
|
|
|
uint32_t fn = 0;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
uint16_t bsn1, bsn2, bsn3;
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gprs_rlc_dl_header_egprs_3 *egprs3;
|
|
|
|
struct gprs_rlc_dl_header_egprs_2 *egprs2;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "Testing retx for MCS %u to reseg_mcs %u\n", mcs, demanded_mcs);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = tbf_init(bts, mcs);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Table 10.4.8a.3.1 of 44.060.
|
|
|
|
* (MCS7, MCS9) to (MCS2, MCS3) is not handled since it is same as
|
|
|
|
* (MCS5, MCS6) to (MCS2, MCS3) transition
|
|
|
|
*/
|
|
|
|
if (!(mcs == 6 && demanded_mcs == 3))
|
|
|
|
return;
|
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first RLC data block BSN 0 */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
egprs2 = (struct gprs_rlc_dl_header_egprs_2 *) msg->data;
|
2017-12-01 16:54:39 +00:00
|
|
|
bsn1 = (egprs2->bsn1_hi << 9) | (egprs2->bsn1_mid << 1) | (egprs2->bsn1_lo);
|
2017-12-15 10:25:14 +00:00
|
|
|
|
|
|
|
NACK(dl_tbf, 0);
|
|
|
|
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(bsn1 == 0);
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
|
|
|
|
/* Send first segment with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, false);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
|
|
|
|
== EGPRS_RESEG_FIRST_SEG_SENT);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
|
|
|
|
OSMO_ASSERT(egprs3->spb == 2);
|
|
|
|
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
OSMO_ASSERT(egprs3->cps == 3);
|
|
|
|
|
|
|
|
/* Send second segment with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, true);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
|
|
|
|
== EGPRS_RESEG_SECOND_SEG_SENT);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
OSMO_ASSERT(egprs3->spb == 3);
|
2017-12-01 16:54:39 +00:00
|
|
|
bsn2 = (egprs3->bsn1_hi << 9) | (egprs3->bsn1_mid << 1) | (egprs3->bsn1_lo);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(bsn2 == bsn1);
|
|
|
|
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
OSMO_ASSERT(egprs3->cps == 3);
|
|
|
|
|
|
|
|
/* Handle (MCS3, MCS3) -> MCS6 case */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + mcs));
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
NACK(dl_tbf, 0);
|
|
|
|
|
2016-08-22 11:51:10 +00:00
|
|
|
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
|
|
|
|
egprs2 = (struct gprs_rlc_dl_header_egprs_2 *) msg->data;
|
|
|
|
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
OSMO_ASSERT(egprs2->cps == 0);
|
2017-12-01 16:54:39 +00:00
|
|
|
bsn3 = (egprs2->bsn1_hi << 9) | (egprs2->bsn1_mid << 1) | (egprs2->bsn1_lo);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(bsn3 == bsn2);
|
|
|
|
|
|
|
|
tbf_cleanup(dl_tbf);
|
|
|
|
}
|
2017-02-08 16:07:40 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void establish_and_use_egprs_dl_tbf_for_spb(struct gprs_rlcmac_bts *bts,
|
2017-02-08 16:07:40 +00:00
|
|
|
unsigned int mcs, unsigned int demanded_mcs)
|
2016-08-22 11:51:10 +00:00
|
|
|
{
|
|
|
|
uint32_t fn = 0;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gprs_rlc_dl_header_egprs_3 *egprs3;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "Testing retx for MCS %u to reseg_mcs %u\n", mcs, demanded_mcs);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = tbf_init(bts, mcs);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Table 10.4.8a.3.1 of 44.060.
|
|
|
|
* (MCS7, MCS9) to (MCS2, MCS3) is not handled since it is same as
|
|
|
|
* (MCS5, MCS6) to (MCS2, MCS3) transition
|
|
|
|
*/
|
|
|
|
/* TODO: Need to support of MCS8 -> MCS6 ->MCS3 transistion
|
|
|
|
* Refer commit be881c028fc4da00c4046ecd9296727975c206a3
|
|
|
|
* dated 2016-02-07 23:45:40 (UTC)
|
|
|
|
*/
|
|
|
|
if (!(((mcs == 5) && (demanded_mcs == 2)) ||
|
|
|
|
((mcs == 6) && (demanded_mcs == 3)) ||
|
|
|
|
((mcs == 4) && (demanded_mcs == 1))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first RLC data block BSN 0 */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
NACK(dl_tbf, 0);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
|
|
|
|
/* Send first segment with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, false);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
|
|
|
|
== EGPRS_RESEG_FIRST_SEG_SENT);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
|
|
|
|
OSMO_ASSERT(egprs3->spb == 2);
|
|
|
|
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
switch (demanded_mcs) {
|
|
|
|
case 3:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 3);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 9);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 11);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
OSMO_ASSERT(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send second segment with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, true);
|
2016-08-22 11:51:10 +00:00
|
|
|
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
|
|
|
|
== EGPRS_RESEG_SECOND_SEG_SENT);
|
|
|
|
|
|
|
|
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
OSMO_ASSERT(egprs3->spb == 3);
|
|
|
|
|
|
|
|
/* Table 10.4.8a.3.1 of 44.060 */
|
|
|
|
switch (demanded_mcs) {
|
|
|
|
case 3:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 3);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 9);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
OSMO_ASSERT(egprs3->cps == 11);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
OSMO_ASSERT(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tbf_cleanup(dl_tbf);
|
|
|
|
}
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
static void establish_and_use_egprs_dl_tbf_for_retx(struct gprs_rlcmac_bts *bts,
|
2017-02-08 16:07:40 +00:00
|
|
|
unsigned int mcs, unsigned int demanded_mcs)
|
2016-07-12 10:20:29 +00:00
|
|
|
{
|
|
|
|
uint32_t fn = 0;
|
|
|
|
gprs_rlcmac_dl_tbf *dl_tbf;
|
|
|
|
struct msgb *msg;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "Testing retx for MCS %u - %u\n", mcs, demanded_mcs);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
dl_tbf = tbf_init(bts, mcs);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
/* For MCS reduction cases like MCS9->MCS6, MCS7->MCS5
|
|
|
|
* The MCS transition are referred from table Table 8.1.1.2
|
|
|
|
* of TS 44.060
|
|
|
|
*/
|
|
|
|
/* TODO: Need to support of MCS8 -> MCS6 transistion
|
|
|
|
* Refer commit be881c028fc4da00c4046ecd9296727975c206a3
|
|
|
|
* dated 2016-02-07 23:45:40 (UTC)
|
|
|
|
*/
|
|
|
|
if (((mcs == 9) && (demanded_mcs < 9)) ||
|
|
|
|
((mcs == 7) && (demanded_mcs < 7))) {
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send 2 RLC data block */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, mcs, 1);
|
|
|
|
|
|
|
|
NACK(dl_tbf, 0);
|
|
|
|
NACK(dl_tbf, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
/* Set the demanded MCS to demanded_mcs */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Retransmit the first RLC data block with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, true);
|
|
|
|
CHECK_NACKED(dl_tbf, mcs, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Retransmit the second RLC data block with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, demanded_mcs, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
} else if (((mcs == 5) && (demanded_mcs > 6)) ||
|
|
|
|
((mcs == 6) && (demanded_mcs > 8))) {
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first RLC data block BSN 0 */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send second RLC data block BSN 1 */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, mcs, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
NACK(dl_tbf, 0);
|
|
|
|
NACK(dl_tbf, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first, second RLC data blocks with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, demanded_mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, demanded_mcs, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
} else if (mcs > 6) {
|
|
|
|
/* No Mcs change cases are handled here for mcs > MCS6*/
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first,second RLC data blocks */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, mcs, 1);
|
|
|
|
|
|
|
|
NACK(dl_tbf, 0);
|
|
|
|
NACK(dl_tbf, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first,second RLC data blocks with demanded_mcs*/
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
|
|
|
CHECK_UNACKED(dl_tbf, mcs, 1);
|
2016-07-12 10:20:29 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
/* No MCS change cases are handled here for mcs <= MCS6*/
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first RLC data block */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
2017-12-15 10:25:14 +00:00
|
|
|
NACK(dl_tbf, 0);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
fn = fn_add_blocks(fn, 1);
|
|
|
|
/* Send first RLC data block with demanded_mcs */
|
2017-12-15 10:25:14 +00:00
|
|
|
MAKE_ACKED(msg, dl_tbf, fn, mcs, true);
|
2016-07-12 10:20:29 +00:00
|
|
|
}
|
2021-03-09 16:18:12 +00:00
|
|
|
/* Clean up pending items in UL controller: */
|
2021-03-29 17:10:19 +00:00
|
|
|
send_empty_block(dl_tbf, dl_tbf->control_ts, fn+50);
|
2016-07-12 10:20:29 +00:00
|
|
|
tbf_cleanup(dl_tbf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_tbf_egprs_retx_dl(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-07-12 10:20:29 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-07-12 10:20:29 +00:00
|
|
|
|
2021-01-14 12:20:55 +00:00
|
|
|
the_pcu->vty.cs_downgrade_threshold = 0;
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
|
2016-08-22 11:51:10 +00:00
|
|
|
/* ARQ II */
|
2021-01-14 12:08:02 +00:00
|
|
|
the_pcu->vty.dl_arq_type = EGPRS_ARQ2;
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2016-07-12 10:20:29 +00:00
|
|
|
|
|
|
|
/* First parameter is current MCS, second one is demanded_mcs */
|
2021-01-14 15:48:38 +00:00
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 6, 6);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 1, 9);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 2, 8);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 5, 7);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 6, 9);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 7, 5);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_retx(bts, 9, 6);
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2021-01-13 17:54:38 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-07-12 10:20:29 +00:00
|
|
|
}
|
|
|
|
|
2016-08-22 11:51:10 +00:00
|
|
|
static void test_tbf_egprs_spb_dl(void)
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-08-22 11:51:10 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2021-01-14 12:20:55 +00:00
|
|
|
the_pcu->vty.cs_downgrade_threshold = 0;
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
/* ARQ I resegmentation support */
|
2021-01-14 12:08:02 +00:00
|
|
|
the_pcu->vty.dl_arq_type = EGPRS_ARQ1;
|
2016-08-22 11:51:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First parameter is current MCS, second one is demanded_mcs
|
|
|
|
* currently only MCS5->MCS2, MCS6->3, MCS4->MCS1 is tested in UT
|
|
|
|
* rest scenarios has been integration tested
|
|
|
|
*/
|
2021-01-14 15:48:38 +00:00
|
|
|
establish_and_use_egprs_dl_tbf_for_spb(bts, 6, 3);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_spb(bts, 5, 2);
|
|
|
|
establish_and_use_egprs_dl_tbf_for_spb(bts, 4, 1);
|
2016-08-22 11:51:10 +00:00
|
|
|
/* check MCS6->(MCS3+MCS3)->MCS6 case */
|
2021-01-14 15:48:38 +00:00
|
|
|
egprs_spb_to_normal_validation(bts, 6, 3);
|
2016-08-22 11:51:10 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-08-22 11:51:10 +00:00
|
|
|
}
|
|
|
|
|
2016-02-04 10:09:19 +00:00
|
|
|
static void test_tbf_egprs_dl()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-02-04 10:09:19 +00:00
|
|
|
uint8_t ts_no = 4;
|
|
|
|
int i;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no);
|
2021-01-14 11:01:42 +00:00
|
|
|
OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0);
|
2016-08-22 11:51:10 +00:00
|
|
|
/* ARQ II */
|
2021-01-14 12:08:02 +00:00
|
|
|
the_pcu->vty.dl_arq_type = EGPRS_ARQ2;
|
2016-02-04 10:09:19 +00:00
|
|
|
|
|
|
|
for (i = 1; i <= 9; i++)
|
2021-01-14 15:48:38 +00:00
|
|
|
establish_and_use_egprs_dl_tbf(bts, i);
|
2016-02-04 10:09:19 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-02-04 10:09:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-01-24 07:06:08 +00:00
|
|
|
static void test_packet_access_rej_prr_no_other_tbfs()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2017-01-24 07:06:08 +00:00
|
|
|
uint32_t fn = 2654218;
|
|
|
|
int ts_no = 7;
|
|
|
|
uint8_t trx_no = 0;
|
|
|
|
uint32_t tlli = 0xffeeddcc;
|
|
|
|
struct gprs_rlcmac_ul_tbf *ul_tbf = NULL;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
ul_tbf = handle_tbf_reject(bts, NULL, tlli,
|
2017-01-24 07:06:08 +00:00
|
|
|
trx_no, ts_no);
|
|
|
|
|
|
|
|
OSMO_ASSERT(ul_tbf != 0);
|
|
|
|
|
|
|
|
/* trigger packet access reject */
|
|
|
|
uint8_t bn = fn2bn(fn);
|
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
rc = gprs_rlcmac_rcv_rts_block(bts,
|
2017-01-24 07:06:08 +00:00
|
|
|
trx_no, ts_no, fn, bn);
|
|
|
|
|
|
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
|
|
|
|
ul_tbf->handle_timeout();
|
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2017-01-24 07:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_packet_access_rej_prr()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2017-01-24 07:06:08 +00:00
|
|
|
uint32_t fn = 2654218;
|
|
|
|
uint16_t qta = 31;
|
|
|
|
int ts_no = 7;
|
|
|
|
uint8_t trx_no = 0;
|
|
|
|
RlcMacUplink_t ulreq = {0};
|
|
|
|
Packet_Resource_Request_t *presreq = NULL;
|
|
|
|
uint8_t ms_class = 11;
|
|
|
|
uint8_t egprs_ms_class = 11;
|
|
|
|
uint32_t rach_fn = fn - 51;
|
|
|
|
uint32_t sba_fn = fn + 52;
|
|
|
|
uint32_t tlli = 0xffeeddcc;
|
|
|
|
MS_Radio_Access_capability_t *pmsradiocap = NULL;
|
|
|
|
Multislot_capability_t *pmultislotcap = NULL;
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, ts_no, 4);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trigger rach till resources(USF) exhaust
|
|
|
|
*/
|
2021-04-22 17:18:13 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
rc = bts_handle_rach(bts, 0x70 + i, rach_fn, qta);
|
2017-01-24 07:06:08 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 17:18:13 +00:00
|
|
|
sba_fn = 52;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
/* fake a resource request */
|
|
|
|
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
|
|
|
|
presreq = &ulreq.u.Packet_Resource_Request;
|
|
|
|
presreq->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
|
|
|
|
presreq->ID.UnionType = 1; /* != 0 */
|
|
|
|
presreq->ID.u.TLLI = tlli + i;
|
|
|
|
presreq->Exist_MS_Radio_Access_capability2 = 1;
|
|
|
|
pmsradiocap = &presreq->MS_Radio_Access_capability2;
|
|
|
|
pmsradiocap->Count_MS_RA_capability_value = 1;
|
|
|
|
pmsradiocap->MS_RA_capability_value[0].u.Content.
|
|
|
|
Exist_Multislot_capability = 1;
|
|
|
|
pmultislotcap = &pmsradiocap->MS_RA_capability_value[0].
|
|
|
|
u.Content.Multislot_capability;
|
|
|
|
|
|
|
|
pmultislotcap->Exist_GPRS_multislot_class = 1;
|
|
|
|
pmultislotcap->GPRS_multislot_class = ms_class;
|
|
|
|
if (egprs_ms_class) {
|
|
|
|
pmultislotcap->Exist_EGPRS_multislot_class = 1;
|
|
|
|
pmultislotcap->EGPRS_multislot_class = egprs_ms_class;
|
|
|
|
}
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-04-22 17:18:13 +00:00
|
|
|
send_ul_mac_block(bts, trx_no, ts_no, &ulreq, sba_fn);
|
|
|
|
sba_fn = fn_next_block(sba_fn);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-04-22 17:18:13 +00:00
|
|
|
/* trigger packet access reject */
|
|
|
|
uint8_t bn = fn2bn(fn);
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-04-22 17:18:13 +00:00
|
|
|
rc = gprs_rlcmac_rcv_rts_block(bts,
|
|
|
|
trx_no, ts_no, fn, bn);
|
|
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
}
|
2017-01-24 07:06:08 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2017-01-24 07:06:08 +00:00
|
|
|
}
|
|
|
|
|
2016-11-11 11:45:10 +00:00
|
|
|
void test_packet_access_rej_epdan()
|
|
|
|
{
|
2021-01-14 13:28:26 +00:00
|
|
|
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
|
2021-01-18 16:14:14 +00:00
|
|
|
struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0);
|
2016-11-11 11:45:10 +00:00
|
|
|
uint32_t tlli = 0xffeeddcc;
|
2019-03-05 15:15:01 +00:00
|
|
|
static uint8_t exp[] = { 0x40, 0x84, 0x7f, 0xf7, 0x6e, 0xe6, 0x41, 0x4b,
|
|
|
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
|
|
|
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
|
|
|
|
};
|
2016-11-11 11:45:10 +00:00
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== start %s ===\n", __func__);
|
2021-01-14 15:48:38 +00:00
|
|
|
setup_bts(bts, 4);
|
|
|
|
static gprs_rlcmac_dl_tbf *dl_tbf = tbf_init(bts, 1);
|
2016-11-11 11:45:10 +00:00
|
|
|
|
|
|
|
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
|
|
|
|
|
|
|
|
struct msgb *msg = dl_tbf->create_packet_access_reject();
|
|
|
|
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "packet reject: %s\n",
|
2016-11-11 11:45:10 +00:00
|
|
|
osmo_hexdump(msg->data, 23));
|
|
|
|
|
2019-03-05 15:15:01 +00:00
|
|
|
if (!msgb_eq_data_print(msg, exp, GSM_MACBLOCK_LEN))
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "%s test failed!\n", __func__);
|
2019-03-05 15:15:01 +00:00
|
|
|
|
2021-01-14 13:28:26 +00:00
|
|
|
TALLOC_FREE(the_pcu);
|
2019-09-09 12:09:48 +00:00
|
|
|
fprintf(stderr, "=== end %s ===\n", __func__);
|
2016-11-11 11:45:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-30 13:50:17 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2015-04-09 17:17:21 +00:00
|
|
|
struct vty_app_info pcu_vty_info = {0};
|
|
|
|
|
2013-10-30 13:50:17 +00:00
|
|
|
tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile TbfTest context");
|
|
|
|
if (!tall_pcu_ctx)
|
|
|
|
abort();
|
|
|
|
|
2017-02-08 16:07:31 +00:00
|
|
|
msgb_talloc_ctx_init(tall_pcu_ctx, 0);
|
2018-04-01 14:54:40 +00:00
|
|
|
osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
|
2013-10-30 13:50:17 +00:00
|
|
|
log_set_use_color(osmo_stderr_target, 0);
|
2021-02-19 13:01:52 +00:00
|
|
|
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
2021-02-19 13:00:48 +00:00
|
|
|
log_set_print_category(osmo_stderr_target, 0);
|
|
|
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
2018-01-24 10:04:59 +00:00
|
|
|
log_parse_category_mask(osmo_stderr_target, "DRLCMAC,1:DRLCMACDATA,3:DRLCMACDL,3:DRLCMACUL,3:"
|
2020-12-10 12:39:21 +00:00
|
|
|
"DRLCMACSCHED,1:DRLCMACMEAS,3:DNS,3:DLBSSGP,3:DPCU,5:"
|
2019-03-07 11:20:42 +00:00
|
|
|
"DL1IF,6:DTBF,1:DTBFUL,1:DTBFDL,1:DLGLOBAL,2:");
|
2015-04-09 17:17:21 +00:00
|
|
|
vty_init(&pcu_vty_info);
|
2019-08-05 12:30:44 +00:00
|
|
|
pcu_vty_init();
|
2013-10-30 13:50:17 +00:00
|
|
|
|
2019-11-07 21:44:04 +00:00
|
|
|
/* Initialize shared UL measurements */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
pcu_l1_meas_set_link_qual(&meas, 12);
|
|
|
|
pcu_l1_meas_set_rssi(&meas, 31);
|
2019-11-07 21:44:04 +00:00
|
|
|
|
2015-06-29 12:18:46 +00:00
|
|
|
test_tbf_base();
|
2013-10-30 13:50:17 +00:00
|
|
|
test_tbf_tlli_update();
|
2015-02-23 13:26:59 +00:00
|
|
|
test_tbf_final_ack(TEST_MODE_STANDARD);
|
|
|
|
test_tbf_final_ack(TEST_MODE_REVERSE_FREE);
|
2015-03-25 09:48:52 +00:00
|
|
|
test_tbf_delayed_release();
|
2015-05-21 09:07:16 +00:00
|
|
|
test_tbf_imsi();
|
2015-04-09 17:17:21 +00:00
|
|
|
test_tbf_exhaustion();
|
2015-06-12 11:41:00 +00:00
|
|
|
test_tbf_dl_llc_loss();
|
2015-05-27 11:03:15 +00:00
|
|
|
test_tbf_single_phase();
|
|
|
|
test_tbf_two_phase();
|
2015-08-21 16:15:38 +00:00
|
|
|
test_tbf_ra_update_rach();
|
|
|
|
test_tbf_dl_flow_and_rach_two_phase();
|
|
|
|
test_tbf_dl_flow_and_rach_single_phase();
|
2015-08-21 13:04:39 +00:00
|
|
|
test_tbf_dl_reuse();
|
2016-01-19 09:44:42 +00:00
|
|
|
test_tbf_gprs_egprs();
|
2016-01-19 14:53:30 +00:00
|
|
|
test_tbf_ws();
|
2016-02-04 10:09:19 +00:00
|
|
|
test_tbf_egprs_two_phase();
|
2016-07-26 12:56:21 +00:00
|
|
|
test_tbf_egprs_two_phase_spb();
|
2016-02-04 10:09:19 +00:00
|
|
|
test_tbf_egprs_dl();
|
2016-07-12 10:20:29 +00:00
|
|
|
test_tbf_egprs_retx_dl();
|
2016-08-22 11:51:10 +00:00
|
|
|
test_tbf_egprs_spb_dl();
|
2016-08-25 11:07:30 +00:00
|
|
|
test_tbf_puan_urbb_len();
|
2016-08-30 10:09:04 +00:00
|
|
|
test_tbf_update_ws();
|
2016-09-15 11:49:54 +00:00
|
|
|
test_tbf_li_decoding();
|
2016-10-25 07:15:24 +00:00
|
|
|
test_tbf_epdan_out_of_rx_window();
|
2016-11-09 10:57:00 +00:00
|
|
|
test_immediate_assign_rej();
|
2017-01-24 10:23:35 +00:00
|
|
|
test_tbf_egprs_two_phase_puan();
|
2016-11-11 11:45:10 +00:00
|
|
|
test_packet_access_rej_epdan();
|
2017-01-24 07:06:08 +00:00
|
|
|
test_packet_access_rej_prr();
|
|
|
|
test_packet_access_rej_prr_no_other_tbfs();
|
2015-05-11 08:32:40 +00:00
|
|
|
|
|
|
|
if (getenv("TALLOC_REPORT_FULL"))
|
|
|
|
talloc_report_full(tall_pcu_ctx, stderr);
|
2013-10-30 13:50:17 +00:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* stubs that should not be reached
|
|
|
|
*/
|
|
|
|
extern "C" {
|
|
|
|
void l1if_pdch_req() { abort(); }
|
|
|
|
void l1if_connect_pdch() { abort(); }
|
|
|
|
void l1if_close_pdch() { abort(); }
|
|
|
|
void l1if_open_pdch() { abort(); }
|
|
|
|
}
|