diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bts.cpp | 158 | ||||
-rw-r--r-- | src/bts.h | 28 | ||||
-rw-r--r-- | src/gprs_rlcmac_ts_alloc.cpp | 10 | ||||
-rw-r--r-- | src/sba.cpp | 42 | ||||
-rw-r--r-- | src/tbf.cpp | 2 |
5 files changed, 203 insertions, 37 deletions
diff --git a/src/bts.cpp b/src/bts.cpp index cfccec9..c116eed 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -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 = 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; + + 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, tfi; + 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; - OSMO_ASSERT(tfi < 32); + 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); + } + } - 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() @@ -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; diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 57197b2..df65767 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -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); diff --git a/src/sba.cpp b/src/sba.cpp index 46c1431..117aa34 100644 --- a/src/sba.cpp +++ b/src/sba.cpp @@ -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; } diff --git a/src/tbf.cpp b/src/tbf.cpp index cbb7e30..fd39fe8 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -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; } |