PDCH allocation across two TRX

Implementation:
PCU keeps track of number PDCH across all the TRXs at BTS context and also keeps number
of active PDCHs in each TRX context. This ratio gives the CAPACITY of each TRX.

1st Phase:
	While selection of TRX, functions get_possible_trxs(for multiple TS)
	and get_possible_trxs_sba(Single block allocation, Ex: during RACH)
	gets possible TRXs based on TFIs availability.
2nd Phase: outcome of TRXs(from get_possible_trxs, get_possible_trxs_sba) will
	be fed to get_suitable_trx function. Which does actual load balancing on each TRX.
	And selects the best fit TRX, based on below equation
	PROBABILITY = MAX_PROBABILITY – ((LOAD * 100)/CAPACITY);

	If same PROBABILITY
		Select the one with higher capacity
	Else
		Find the TRX with higher PROBABILITY

	MAX_PROBABILITY  = 65535;
	LOAD: Initialized to 0, Later gets incremented with number of TS allocated.
	and decremented whle TBF deletion, based on number of TS allocated

Below are the test executed on Unit test environment
1)	2 TRXs, with same Capacity
2)	2 TRX with ½ capacity
3)	2 TRXs with ¼ capacity
4)	2 TRX with UL and DL allocation to ensure Tbfs on both direction is hosted on same TRX
5)	2 TRX with same Capacity and  DL TBF creation and deletion scenarios to ensure proper
	load balancing criteria for actual Load.

Below are the Test executed on Integration setup with Ettus B200 setup with 2
	TRXs with same CAPACITY.
1)	TRX allocation during RACH procedure(SBA allocation)
2)	TRX allocation during DL TBF creation with multi time slots(4 time slots)
3)	TRX allocation while Ping Test
4)	TRX allocation while UDP test
5)	TRX allocation for web browsing.
6)	2 MS test with each TRX sharing 1 MS. Received aggregate throughput of
	446 kbps(223 Kbps each)

Limitation:
1)	 BSSGP flow control needs to be tuned since test with 2 MS with each MS on different TRX
	runs for 20 mins
2)	USF resource availibility is not checked while selecting the TRX as existing implementation

Change-Id: Ifb61a7862d55af828383b6dfe728628e546ed12b
Related: OS# 1775
This commit is contained in:
aravind sirsikar 2016-12-30 12:24:38 +05:30
parent d3ae14c18f
commit 9ddc3c7845
8 changed files with 2008 additions and 39 deletions

View File

@ -188,11 +188,13 @@ BTS::BTS()
{
memset(&m_bts, 0, sizeof(m_bts));
m_bts.bts = this;
m_total_pdch = 0;
/* initialize back pointers */
for (size_t trx_no = 0; trx_no < ARRAY_SIZE(m_bts.trx); ++trx_no) {
struct gprs_rlcmac_trx *trx = &m_bts.trx[trx_no];
trx->trx_no = trx_no;
trx->num_pdch = 0;
trx->current_load = 0;
trx->bts = this;
for (size_t ts_no = 0; ts_no < ARRAY_SIZE(trx->pdch); ++ts_no) {
@ -417,9 +419,82 @@ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir,
uint8_t *_trx, int8_t use_trx)
{
struct gprs_rlcmac_pdch *pdch;
uint32_t free_tfis;
uint32_t free_tfis = 0xffffffff;
uint8_t ts, tfi;
bool possible_trx[8];
int ret;
/* This function will get list of possible TRXs */
ret = get_possible_trxs(dir, possible_trx, use_trx);
if (ret < 0)
return -EBUSY;
if (use_trx >= 0)
*_trx = use_trx;
else
*_trx = get_suitable_trx(possible_trx);
LOGP(DRLCMAC, LOGL_DEBUG,
"Searching for first unallocated TFI: TRX=%d\n", *_trx);
for (ts = 0; ts < 8; ts++) {
pdch = &m_bts.trx[*_trx].pdch[ts];
free_tfis &= ~pdch->assigned_tfi(dir);
}
/* find the first */
for (tfi = 0; tfi < 32; tfi++) {
if (free_tfis & 1 << tfi)
break;
}
OSMO_ASSERT(tfi < 32);
LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);
return tfi;
}
/*
* Search for free TFI and return TFI, TRX.
* This method returns the first TFI that is currently not used in any PDCH of
* a TRX. The first TRX that contains such an TFI is returned. Negative values
* indicate errors.
*/
int BTS::get_possible_trxs_sba(
bool *_trx)
{
uint8_t trx;
bool has_pdch = false;
uint8_t trx_from, trx_to, trx, ts, tfi;
for (trx = 0; trx < 8; trx++) {
if (bts_data()->trx[trx].num_pdch) {
_trx[trx] = true;
has_pdch = true;
LOGP(DRLCMAC, LOGL_DEBUG, " Valid TRX=%d.\n", trx);
} else {
_trx[trx] = false;
LOGP(DRLCMAC, LOGL_DEBUG, " Not valid TRX=%d.\n", trx);
}
}
if (has_pdch)
return 0;
return -EINVAL;
}
/*
* This method loops through all possible TRX and
* returns subset of possible TRXs based on availability.
*/
int BTS::get_possible_trxs(enum gprs_rlcmac_tbf_direction dir,
bool *_trx, int8_t use_trx)
{
struct gprs_rlcmac_pdch *pdch;
uint32_t free_tfis;
uint32_t is_tfis_available = false;
bool has_pdch = false;
uint8_t trx_from, trx_to, trx, ts;
if (use_trx >= 0 && use_trx < 8)
trx_from = trx_to = use_trx;
@ -442,8 +517,12 @@ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir,
trx_has_pdch = true;
has_pdch = true;
}
if (trx_has_pdch && free_tfis)
break;
if (trx_has_pdch && free_tfis) {
_trx[trx] = true;
is_tfis_available = true;
} else {
_trx[trx] = false;
}
free_tfis = 0;
}
@ -452,26 +531,69 @@ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir,
return -EINVAL;
}
if (!free_tfis) {
if (!is_tfis_available) {
LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n");
return -EBUSY;
}
return 0;
}
/*
* This method loops through all subset of TRXs provided by
* get_possible_trxs and does the load balancing algorithm. and
* selects best TRX possible based on load and capacity
*/
int BTS::get_suitable_trx(bool *avail_trx)
{
uint8_t trx_from, trx_to, trx;
uint32_t select_probability = 0;
uint32_t temp_probability = 0;
int selected_trx = -1;
bool is_better_trx = false;
LOGP(DRLCMAC, LOGL_DEBUG,
"Searching for first unallocated TFI: TRX=%d\n", trx);
trx_from = 0;
trx_to = 7;
/* find the first */
for (tfi = 0; tfi < 32; tfi++) {
if (free_tfis & 1 << tfi)
break;
for (trx = trx_from; trx <= trx_to; trx++) {
/* Check if this TRX is in possible list */
if (!avail_trx[trx])
continue;
is_better_trx = false;
temp_probability = MAX_LOAD_PROBABILITY -
(get_num_pdch() * 100 *
m_bts.trx[trx].current_load)
/ m_bts.trx[trx].num_pdch;
LOGP(DRLCMAC, LOGL_DEBUG, "trx(%d) cur load(%d)"
" numpdch(%d) prob1(%u) seleprob(%u)"
" btsnumpdch(%d)\n", trx,
m_bts.trx[trx].current_load,
m_bts.trx[trx].num_pdch,
temp_probability, select_probability,
get_num_pdch());
if (temp_probability >= select_probability) {
if (temp_probability > select_probability)
is_better_trx = true;
else if (temp_probability == select_probability)
if (selected_trx >= 0 || selected_trx < 8)
if (m_bts.trx[selected_trx].num_pdch
< m_bts.trx[trx].num_pdch)
is_better_trx = true;
}
if (is_better_trx) {
selected_trx = trx;
select_probability =
temp_probability;
LOGP(DRLCMAC, LOGL_DEBUG, "selected pro(%u)"
"selected_trx(%d)\n",
select_probability, selected_trx);
}
}
OSMO_ASSERT(tfi < 32);
LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);
*_trx = trx;
return tfi;
return selected_trx;
}
int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
@ -783,13 +905,17 @@ void gprs_rlcmac_pdch::enable()
{
/* TODO: Check if there are still allocated resources.. */
INIT_LLIST_HEAD(&paging_list);
trx->num_pdch++;
m_is_enabled = 1;
bts()->increment_num_pdch();
}
void gprs_rlcmac_pdch::disable()
{
/* TODO.. kick free_resources once we know the TRX/TS we are on */
m_is_enabled = 0;
trx->num_pdch--;
bts()->decrement_num_pdch();
}
void gprs_rlcmac_pdch::free_resources()

View File

@ -44,6 +44,7 @@ extern "C" {
#define LLC_CODEL_USE_DEFAULT (-1)
#define MAX_GPRS_CS 9
#define MAX_LOAD_PROBABILITY 0xffffffff
struct BTS;
struct GprsMs;
@ -136,7 +137,8 @@ struct gprs_rlcmac_trx {
/* back pointers */
struct BTS *bts;
uint8_t trx_no;
uint8_t current_load;
uint8_t num_pdch;
#ifdef __cplusplus
void reserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots);
void unreserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots);
@ -345,6 +347,9 @@ public:
gprs_rlcmac_ul_tbf *ul_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts);
int tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx);
int get_possible_trxs(enum gprs_rlcmac_tbf_direction dir,
bool *_trx, int8_t use_trx);
int get_suitable_trx(bool *suitable_trx);
int rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn);
uint8_t is_single_block(uint16_t ra, enum ph_burst_type burst_type,
@ -451,6 +456,10 @@ public:
void ms_present(int32_t n);
int32_t ms_present_get();
void increment_num_pdch();
void decrement_num_pdch();
uint8_t get_num_pdch() const;
int get_possible_trxs_sba(bool *_trx);
/*
* Below for C interface for the VTY
@ -476,6 +485,8 @@ private:
/* list of downlink TBFs */
LListHead<gprs_rlcmac_tbf> m_dl_tbfs;
/* The summation of all the PDCH across all TRX for this BTS*/
uint8_t m_total_pdch;
private:
/* disable copying to avoid slicing */
BTS(const BTS&);
@ -487,6 +498,21 @@ inline int BTS::current_frame_number() const
return m_cur_fn;
}
inline void BTS::increment_num_pdch()
{
m_total_pdch++;
}
inline void BTS::decrement_num_pdch()
{
m_total_pdch--;
}
inline uint8_t BTS::get_num_pdch() const
{
return m_total_pdch;
}
inline SBAController *BTS::sba()
{
return &m_sba;

View File

@ -383,8 +383,11 @@ static int tfi_find_free(BTS *bts, const GprsMs *ms,
int tfi;
uint8_t trx_no;
if (use_trx == -1 && ms->current_trx())
LOGP(DRLCMAC, LOGL_DEBUG, " USE trx = %d \n",use_trx);
if (use_trx == -1 && ms->current_trx()) {
use_trx = ms->current_trx()->trx_no;
LOGP(DRLCMAC, LOGL_DEBUG, " MS alive = %d \n",use_trx);
}
tfi = bts->tfi_find_free(dir, &trx_no, use_trx);
if (tfi < 0)
@ -393,6 +396,8 @@ static int tfi_find_free(BTS *bts, const GprsMs *ms,
if (trx_no_)
*trx_no_ = trx_no;
LOGP(DRLCMAC, LOGL_DEBUG, " TREE trx = %d TFI = %d\n", *trx_no_, tfi);
return tfi;
}
@ -479,6 +484,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
}
tbf_->trx = trx;
trx->current_load++;
/* the only one TS is the common TS */
tbf_->first_ts = tbf_->first_common_ts = ts;
ms_->set_reserved_slots(trx, 1 << ts, 1 << ts);
@ -1000,6 +1006,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
if (!(dl_slots & (1 << ts)))
continue;
trx->current_load++;
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
"%d\n", ts);
assign_dlink_tbf(&trx->pdch[ts], dl_tbf, tfi);
@ -1012,6 +1019,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
continue;
OSMO_ASSERT(usf[ts] >= 0);
trx->current_load++;
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
"%d\n", ts);

View File

@ -49,8 +49,27 @@ int SBAController::alloc(
struct gprs_rlcmac_pdch *pdch;
struct gprs_rlcmac_sba *sba;
int8_t trx, ts;
int8_t ts;
uint32_t fn;
bool trxs[8];
int selected_trx;
int ret;
ret = m_bts.get_possible_trxs_sba(trxs);
if (ret == -EINVAL)
return -EINVAL;
selected_trx = m_bts.get_suitable_trx(trxs);
for (ts = 7; ts >= 0; ts--) {
pdch = &m_bts.bts_data()->trx[selected_trx].pdch[ts];
if (!pdch->is_enabled())
continue;
break;
}
if (ts < 0)
return -EINVAL;
sba = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_sba);
if (!sba)
@ -59,25 +78,10 @@ int SBAController::alloc(
if (!gsm48_ta_is_valid(ta))
return -EINVAL;
for (trx = 0; trx < 8; trx++) {
for (ts = 7; ts >= 0; ts--) {
pdch = &m_bts.bts_data()->trx[trx].pdch[ts];
if (!pdch->is_enabled())
continue;
break;
}
if (ts >= 0)
break;
}
if (trx == 8) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
talloc_free(sba);
return -EINVAL;
}
fn = (pdch->last_rts_fn + AGCH_START_OFFSET) % 2715648;
sba->trx_no = trx;
sba->trx_no = selected_trx;
sba->ts_no = ts;
sba->fn = fn;
sba->ta = ta;
@ -85,9 +89,11 @@ int SBAController::alloc(
llist_add(&sba->list, &m_sbas);
m_bts.sba_allocated();
*_trx = trx;
*_trx = selected_trx;
*_ts = ts;
*_fn = fn;
LOGP(DRLCMAC, LOGL_DEBUG, " sba fn=%d ts = %d trx = %d\n", fn, ts, selected_trx);
return 0;
}

View File

@ -395,7 +395,7 @@ static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
for (ts = 0; ts < 8; ts++) {
if (!tbf->pdch[ts])
continue;
tbf->trx->current_load--;
tbf->pdch[ts]->detach_tbf(tbf);
tbf->pdch[ts] = NULL;
}

View File

@ -3350,6 +3350,263 @@ static void test_packet_access_rej_prr()
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test_same_capacity()
{
BTS the_bts;
static gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t trx_no = 0xff;
uint8_t ms_class = 1;
uint8_t egprs_ms_class = 1;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, 4);
the_bts.bts_data()->trx[0].pdch[5].enable();
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[1].pdch[4].enable();
the_bts.bts_data()->trx[1].pdch[5].enable();
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test_1_2_capacity()
{
BTS the_bts;
static gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t trx_no = 0xff;
uint8_t ms_class = 1;
uint8_t egprs_ms_class = 1;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, 4);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[0].pdch[5].enable();
the_bts.bts_data()->trx[1].pdch[4].enable();
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test_1_4_capacity()
{
BTS the_bts;
static gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t trx_no = 0xff;
uint8_t ms_class = 1;
uint8_t egprs_ms_class = 1;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, 4);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[0].pdch[5].enable();
the_bts.bts_data()->trx[0].pdch[6].enable();
the_bts.bts_data()->trx[0].pdch[7].enable();
the_bts.bts_data()->trx[1].pdch[0].enable();
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test_release_alloc()
{
BTS the_bts;
static gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t trx_no = 0xff;
uint8_t ms_class = 1;
uint8_t egprs_ms_class = 1;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, 4);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[0].pdch[5].enable();
the_bts.bts_data()->trx[1].pdch[0].enable();
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
tbf_free(dl_tbf);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
tbf_free(dl_tbf);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
tbf_free(dl_tbf);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test_same_capacity_dl_ul_combined()
{
BTS the_bts;
static gprs_rlcmac_dl_tbf *dl_tbf;
static gprs_rlcmac_ul_tbf *ul_tbf;
uint8_t trx_no = 0xff;
uint8_t ms_class = 1;
uint8_t egprs_ms_class = 1;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, 4);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[1].pdch[4].enable();
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
ul_tbf = tbf_alloc_ul(the_bts.bts_data(),
dl_tbf->trx->trx_no,
dl_tbf->ms_class(), dl_tbf->ms()->egprs_ms_class(),
dl_tbf->tlli(), dl_tbf->ta(), dl_tbf->ms());
OSMO_ASSERT(ul_tbf->trx->trx_no == 0);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 1);
dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), NULL, trx_no,
ms_class, egprs_ms_class, 1);
OSMO_ASSERT(dl_tbf->trx->trx_no == 0);
ul_tbf = tbf_alloc_ul(the_bts.bts_data(),
dl_tbf->trx->trx_no,
dl_tbf->ms_class(), dl_tbf->ms()->egprs_ms_class(),
dl_tbf->tlli(), dl_tbf->ta(), dl_tbf->ms());
OSMO_ASSERT(ul_tbf->trx->trx_no == 0);
printf("=== end %s ===\n", __func__);
}
void test_multi_trx_test()
{
printf("=== start %s ===\n", __func__);
test_multi_trx_test_same_capacity();
test_multi_trx_test_1_2_capacity();
test_multi_trx_test_1_4_capacity();
test_multi_trx_test_release_alloc();
test_multi_trx_test_same_capacity_dl_ul_combined();
printf("=== end %s ===\n", __func__);
}
void test_packet_access_rej_epdan()
{
BTS the_bts;
@ -3420,6 +3677,7 @@ int main(int argc, char **argv)
test_tbf_egprs_two_phase_puan();
test_packet_access_rej_prr();
test_packet_access_rej_prr_no_other_tbfs();
test_multi_trx_test();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);

File diff suppressed because it is too large Load Diff

View File

@ -81,3 +81,15 @@ packet reject: 40 84 7f f7 6e e6 41 4b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
=== end test_packet_access_rej_prr ===
=== start test_packet_access_rej_prr_no_other_tbfs ===
=== end test_packet_access_rej_prr_no_other_tbfs ===
=== start test_multi_trx_test ===
=== start test_multi_trx_test_same_capacity ===
=== end test_multi_trx_test_same_capacity ===
=== start test_multi_trx_test_1_2_capacity ===
=== end test_multi_trx_test_1_2_capacity ===
=== start test_multi_trx_test_1_4_capacity ===
=== end test_multi_trx_test_1_4_capacity ===
=== start test_multi_trx_test_release_alloc ===
=== end test_multi_trx_test_release_alloc ===
=== start test_multi_trx_test_same_capacity_dl_ul_combined ===
=== end test_multi_trx_test_same_capacity_dl_ul_combined ===
=== end test_multi_trx_test ===