aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-03-09 17:18:12 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2021-03-15 19:32:36 +0100
commit99360a304f22980cea3dd6c5c31f22493de5f7f7 (patch)
treeb2536a6e8a115afb47271159588731738c283c06 /src
parent15c58ace7523d2ead00307d3e19807918007e46c (diff)
Replace PollController with newly added PDCH UL Controller
TbfTest is updated to submit empty blocks to have somehow meaningful output (at least as meaningful test results as before, not much). That's because we must update bts->curr_fn to have polls expire. Related: OS#5020 Change-Id: I683ca738ce5a133c49c36a1d94439a942d64a831
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bts.cpp53
-rw-r--r--src/bts.h4
-rw-r--r--src/pdch.cpp55
-rw-r--r--src/pdch_ul_controller.c61
-rw-r--r--src/pdch_ul_controller.h4
-rw-r--r--src/poll_controller.cpp70
-rw-r--r--src/poll_controller.h45
-rw-r--r--src/tbf.cpp27
-rw-r--r--src/tbf.h1
10 files changed, 125 insertions, 197 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ab9aeebe..e1225b0a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,7 +63,6 @@ libgprs_la_SOURCES = \
bts.cpp \
pdch.cpp \
pdch_ul_controller.c \
- poll_controller.cpp \
encoding.cpp \
sba.c \
decoding.cpp \
@@ -102,7 +101,6 @@ noinst_HEADERS = \
bts.h \
pdch.h \
pdch_ul_controller.h \
- poll_controller.h \
encoding.h \
sba.h \
rlc.h \
diff --git a/src/bts.cpp b/src/bts.cpp
index a7d475cd..9f78c8b8 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -19,7 +19,6 @@
*/
#include <bts.h>
-#include <poll_controller.h>
#include <tbf.h>
#include <tbf_ul.h>
#include <encoding.h>
@@ -212,7 +211,6 @@ static int bts_talloc_destructor(struct gprs_rlcmac_bts* bts)
* m_ms_store's destructor */
bts->ms_store->cleanup();
delete bts->ms_store;
- delete bts->pollController;
if (bts->ratectrs) {
rate_ctr_group_free(bts->ratectrs);
@@ -244,7 +242,6 @@ struct gprs_rlcmac_bts* bts_alloc(struct gprs_pcu *pcu, uint8_t bts_nr)
bts->pcu = pcu;
bts->nr = bts_nr;
- bts->pollController = new PollController(*bts);
bts->ms_store = new GprsMsStorage(bts);
bts->cur_fn = 0;
@@ -295,16 +292,9 @@ void bts_set_current_frame_number(struct gprs_rlcmac_bts *bts, int fn)
/* The UL frame numbers lag 3 behind the DL frames and the data
* indication is only sent after all 4 frames of the block have been
* received. Sometimes there is an idle frame between the end of one
- * and start of another frame (every 3 blocks). So the timeout should
- * definitely be there if we're more than 8 frames past poll_fn. Let's
- * stay on the safe side and say 13 or more. An additional delay can
- * happen due to the block processing time in the DSP, so the delay of
- * decoded blocks relative to the timing clock can be much larger.
- * Values up to 50 frames have been observed under load. */
- const static int max_delay = 60;
+ * and start of another frame (every 3 blocks). */
bts->cur_fn = fn;
- bts->pollController->expireTimedout(bts->cur_fn, max_delay);
}
static inline int delta_fn(int fn, int to)
@@ -341,8 +331,6 @@ void bts_set_current_block_frame_number(struct gprs_rlcmac_bts *bts, int fn, uns
if (delay < fn_update_ok_min_delay || delay > fn_update_ok_max_delay ||
bts_current_frame_number(bts) == 0)
bts->cur_fn = fn;
-
- bts->pollController->expireTimedout(fn, max_delay);
}
int bts_add_paging(struct gprs_rlcmac_bts *bts, uint8_t chan_needed, const struct osmo_mobile_identity *mi)
@@ -485,36 +473,6 @@ static inline bool tbf_check(gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t trx_no,
return false;
}
-struct gprs_rlcmac_dl_tbf *bts_dl_tbf_by_poll_fn(struct gprs_rlcmac_bts *bts, uint32_t fn, uint8_t trx, uint8_t ts)
-{
- struct llist_item *pos;
- struct gprs_rlcmac_tbf *tbf;
-
- /* only one TBF can poll on specific TS/FN, because scheduler can only
- * schedule one downlink control block (with polling) at a FN per TS */
- llist_for_each_entry(pos, &bts->dl_tbfs, list) {
- tbf = (struct gprs_rlcmac_tbf *)pos->entry;
- if (tbf_check(tbf, fn, trx, ts))
- return as_dl_tbf(tbf);
- }
- return NULL;
-}
-
-struct gprs_rlcmac_ul_tbf *bts_ul_tbf_by_poll_fn(struct gprs_rlcmac_bts *bts, uint32_t fn, uint8_t trx, uint8_t ts)
-{
- struct llist_item *pos;
- struct gprs_rlcmac_tbf *tbf;
-
- /* only one TBF can poll on specific TS/FN, because scheduler can only
- * schedule one downlink control block (with polling) at a FN per TS */
- llist_for_each_entry(pos, &bts->ul_tbfs, list) {
- tbf = (struct gprs_rlcmac_tbf *)pos->entry;
- if (tbf_check(tbf, fn, trx, ts))
- return as_ul_tbf(tbf);
- }
- return NULL;
-}
-
/* lookup downlink TBF Entity (by TFI) */
struct gprs_rlcmac_dl_tbf *bts_dl_tbf_by_tfi(struct gprs_rlcmac_bts *bts, uint8_t tfi, uint8_t trx, uint8_t ts)
{
@@ -1162,13 +1120,16 @@ void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta)
void bts_update_tbf_ta(struct gprs_rlcmac_bts *bts, const char *p, uint32_t fn,
uint8_t trx_no, uint8_t ts, int8_t ta, bool is_rach)
{
- struct gprs_rlcmac_ul_tbf *tbf =
- bts_ul_tbf_by_poll_fn(bts, fn, trx_no, ts);
- if (!tbf)
+ struct gprs_rlcmac_pdch *pdch = &bts->trx[trx_no].pdch[ts];
+ struct pdch_ulc_node *poll = pdch_ulc_get_node(pdch->ulc, fn);
+ struct gprs_rlcmac_ul_tbf *tbf;
+ if (!poll || poll->type !=PDCH_ULC_NODE_TBF_POLL ||
+ poll->tbf_poll.poll_tbf->direction != GPRS_RLCMAC_UL_TBF)
LOGP(DL1IF, LOGL_DEBUG, "[%s] update TA = %u ignored due to "
"unknown UL TBF on TRX = %d, TS = %d, FN = %d\n",
p, ta, trx_no, ts, fn);
else {
+ tbf = as_ul_tbf(poll->tbf_poll.poll_tbf);
/* we need to distinguish TA information provided by L1
* from PH-DATA-IND and PHY-RA-IND so that we can properly
* update TA for given TBF
diff --git a/src/bts.h b/src/bts.h
index 8070abb1..a459c2ec 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -195,7 +195,6 @@ struct chan_req_params {
bool single_block;
};
-struct PollController;
struct GprsMsStorage;
struct pcu_l1_meas;
@@ -251,7 +250,6 @@ struct gprs_rlcmac_bts {
int cur_blk_fn;
uint8_t max_cs_dl, max_cs_ul;
uint8_t max_mcs_dl, max_mcs_ul;
- struct PollController *pollController;
struct rate_ctr_group *ratectrs;
struct osmo_stat_item_group *statg;
@@ -272,8 +270,6 @@ int bts_add_paging(struct gprs_rlcmac_bts *bts, uint8_t chan_needed, const struc
uint32_t bts_rfn_to_fn(const struct gprs_rlcmac_bts *bts, int32_t rfn);
-struct gprs_rlcmac_dl_tbf *bts_dl_tbf_by_poll_fn(struct gprs_rlcmac_bts *bts, uint32_t fn, uint8_t trx, uint8_t ts);
-struct gprs_rlcmac_ul_tbf *bts_ul_tbf_by_poll_fn(struct gprs_rlcmac_bts *bts, uint32_t fn, uint8_t trx, uint8_t ts);
struct gprs_rlcmac_dl_tbf *bts_dl_tbf_by_tfi(struct gprs_rlcmac_bts *bts, uint8_t tfi, uint8_t trx, uint8_t ts);
struct gprs_rlcmac_ul_tbf *bts_ul_tbf_by_tfi(struct gprs_rlcmac_bts *bts, uint8_t tfi, uint8_t trx, uint8_t ts);
diff --git a/src/pdch.cpp b/src/pdch.cpp
index 1e541176..727ffc63 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -306,12 +306,10 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
uint32_t tlli = packet->TLLI;
GprsMs *ms = bts_ms_by_tlli(bts(), tlli, GSM_RESERVED_TMSI);
gprs_rlcmac_ul_tbf *ul_tbf;
+ struct pdch_ulc_node *poll;
- tbf = bts_ul_tbf_by_poll_fn(bts(), fn, trx_no(), ts_no);
- if (!tbf)
- tbf = bts_dl_tbf_by_poll_fn(bts(), fn, trx_no(), ts_no);
-
- if (!tbf) {
+ poll = pdch_ulc_get_node(ulc, fn);
+ if (!poll || poll->type !=PDCH_ULC_NODE_TBF_POLL || !poll->tbf_poll.poll_tbf) {
LOGPDCH(this, DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
"unknown FN=%u TLLI=0x%08x (TRX %d TS %d)\n",
fn, tlli, trx_no(), ts_no);
@@ -326,6 +324,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
ms_dl_tbf(ms) ? ms_dl_tbf(ms)->state_name() : "None");
return;
}
+ tbf = poll->tbf_poll.poll_tbf;
/* Reset N3101 counter: */
tbf->n_reset(N3101);
@@ -334,6 +333,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
LOGPTBF(tbf, LOGL_DEBUG, "RX: [PCU <- BTS] Packet Control Ack\n");
TBF_POLL_SCHED_UNSET(tbf);
+ pdch_ulc_release_fn(ulc, fn);
/* check if this control ack belongs to packet uplink ack */
ul_tbf = as_ul_tbf(tbf);
@@ -426,6 +426,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_nack, uint32_t fn, struct pcu_l1_meas *meas)
{
int8_t tfi = 0; /* must be signed */
+ struct pdch_ulc_node *poll;
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
int num_blocks;
@@ -435,13 +436,14 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
char show_bits[RLC_GPRS_WS + 1];
tfi = ack_nack->DOWNLINK_TFI;
- tbf = bts_dl_tbf_by_poll_fn(bts(), fn, trx_no(), ts_no);
- if (!tbf) {
+ poll = pdch_ulc_get_node(ulc, fn);
+ if (!poll || poll->type != PDCH_ULC_NODE_TBF_POLL) {
LOGPDCH(this, DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
"unknown FN=%u TFI=%d (TRX %d TS %d)\n",
fn, tfi, trx_no(), ts_no);
return;
}
+ tbf = as_dl_tbf(poll->tbf_poll.poll_tbf);
if (tbf->tfi() != tfi) {
LOGPTBFDL(tbf, LOGL_NOTICE,
"PACKET DOWNLINK ACK with wrong TFI=%d, ignoring!\n", tfi);
@@ -453,6 +455,7 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
if (tbf->handle_ack_nack())
LOGPTBF(tbf, LOGL_NOTICE, "Recovered downlink ack\n");
+ pdch_ulc_release_fn(ulc, fn);
LOGPTBF(tbf, LOGL_DEBUG, "RX: [PCU <- BTS] Packet Downlink Ack/Nack\n");
@@ -493,6 +496,7 @@ void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nac
{
int8_t tfi = 0; /* must be signed */
struct gprs_rlcmac_dl_tbf *tbf;
+ struct pdch_ulc_node *poll;
gprs_rlc_dl_window *window;
int rc;
int num_blocks;
@@ -502,13 +506,14 @@ void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nac
int bsn_begin, bsn_end;
tfi = ack_nack->DOWNLINK_TFI;
- tbf = bts_dl_tbf_by_poll_fn(bts(), fn, trx_no(), ts_no);
- if (!tbf) {
+ poll = pdch_ulc_get_node(ulc, fn);
+ if (!poll || poll->type !=PDCH_ULC_NODE_TBF_POLL) {
LOGPDCH(this, DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
"unknown FN=%u TFI=%d (TRX %d TS %d)\n",
fn, tfi, trx_no(), ts_no);
return;
}
+ tbf = as_dl_tbf(poll->tbf_poll.poll_tbf);
if (tbf->tfi() != tfi) {
LOGPDCH(this, DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
"wrong TFI=%d, ignoring!\n", tfi);
@@ -520,6 +525,7 @@ void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nac
if (tbf->handle_ack_nack())
LOGPTBF(tbf, LOGL_NOTICE, "Recovered EGPRS downlink ack\n");
+ pdch_ulc_release_fn(ulc, fn);
LOGPTBF(tbf, LOGL_DEBUG,
"RX: [PCU <- BTS] EGPRS Packet Downlink Ack/Nack\n");
@@ -694,6 +700,7 @@ return_unref:
void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *report, uint32_t fn)
{
struct gprs_rlcmac_sba *sba;
+ struct pdch_ulc_node *poll;
GprsMs *ms;
ms = bts_ms_by_tlli(bts(), report->TLLI, GSM_RESERVED_TMSI);
@@ -703,9 +710,23 @@ void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *repor
ms = bts_alloc_ms(bts(), 0, 0);
ms_set_tlli(ms, report->TLLI);
}
- if ((sba = pdch_ulc_get_sba(this->ulc, fn))) {
- ms_set_ta(ms, sba->ta);
- sba_free(sba);
+ if ((poll = pdch_ulc_get_node(ulc, fn))) {
+ switch (poll->type) {
+ case PDCH_ULC_NODE_TBF_USF:
+ break;
+ case PDCH_ULC_NODE_TBF_POLL:
+ LOGPDCH(this, DRLCMAC, LOGL_INFO, "FN=%" PRIu32 " Rx Meas Report "
+ "on RRBP POLL, this probably means a DL/CTRL ACK/NACk will "
+ "need to be polled again later\n", fn);
+ TBF_POLL_SCHED_UNSET(poll->tbf_poll.poll_tbf);
+ pdch_ulc_release_fn(ulc, fn);
+ break;
+ case PDCH_ULC_NODE_SBA:
+ sba = poll->sba.sba;
+ ms_set_ta(ms, sba->ta);
+ sba_free(sba);
+ break;
+ }
}
gprs_rlcmac_meas_rep(ms, report);
}
@@ -795,6 +816,7 @@ int gprs_rlcmac_pdch::rcv_control_block(const uint8_t *data, uint8_t data_len,
"FN=%u RX: [PCU <- BTS] unknown control block(%d) received\n",
fn, ul_control_block->u.MESSAGE_TYPE);
}
+
free_ret:
talloc_free(ul_control_block);
bitvec_free(rlc_block);
@@ -809,13 +831,8 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
bts_set_current_frame_number(trx->bts, fn);
/* No successfully decoded UL block was received during this FN: */
- if (len == 0) {
- /* TODO: Here, in the future, it can be checked whether a UL block was expected for:
- * - UL/DL TBFs: RRBP poll pending (bts->pollController->expireTimedout)
- * - UL TBFs: USF poll pending (we don't store this info in ul_tbf yet) -> inc N3101 (OS#5033)
- */
+ if (len == 0)
return 0;
- }
enum CodingScheme cs = mcs_get_by_size_ul(len);
if (!cs) {
@@ -1007,6 +1024,8 @@ void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf)
m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi());
m_tbfs[tbf->direction][tbf->tfi()] = NULL;
+ pdch_ulc_release_tbf(ulc, tbf);
+
LOGPDCH(this, DRLCMAC, LOGL_INFO, "Detaching %s, %d TBFs, "
"USFs = %02x, TFIs = %08x.\n",
tbf->name(), m_num_tbfs[tbf->direction],
diff --git a/src/pdch_ul_controller.c b/src/pdch_ul_controller.c
index ecd3691e..38e68931 100644
--- a/src/pdch_ul_controller.c
+++ b/src/pdch_ul_controller.c
@@ -25,6 +25,7 @@
#include "bts.h"
#include "sba.h"
#include "pdch.h"
+#include "pcu_utils.h"
/* TS 44.060 Table 10.4.5.1 states maximum RRBP is N + 26. Give extra space for time diff between Tx and Rx? */
#define MAX_FN_RESERVED (27 + 50)
@@ -83,6 +84,22 @@ bool pdch_ulc_fn_is_free(struct pdch_ulc *ulc, uint32_t fn)
return !pdch_ulc_get_node(ulc, fn);
}
+int pdch_ulc_get_next_free_rrbp_fn(struct pdch_ulc *ulc, uint32_t fn, uint32_t *poll_fn, unsigned int *rrbp)
+{
+ /* TODO: support other RRBP offsets, see TS 44.060 able 10.4.5.1 */
+ uint32_t new_poll_fn = next_fn(fn, 13);
+ if (!pdch_ulc_fn_is_free(ulc, new_poll_fn)) {
+ LOGPDCH(ulc->pdch, DRLCMAC, LOGL_ERROR, "Polling is already scheduled "
+ "for single block allocation at FN=%u\n", fn);
+ return -EBUSY;
+ }
+
+ *poll_fn = new_poll_fn;
+ *rrbp = 0;
+
+ return 0;
+}
+
static struct pdch_ulc_node *_alloc_node(struct pdch_ulc *ulc, uint32_t fn)
{
struct pdch_ulc_node *node;
@@ -126,7 +143,10 @@ int pdch_ulc_reserve_tbf_usf(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcm
int pdch_ulc_reserve_tbf_poll(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_tbf *tbf)
{
- return 0; /* TODO: implement */
+ struct pdch_ulc_node *item = _alloc_node(ulc, fn);
+ item->type = PDCH_ULC_NODE_TBF_POLL;
+ item->tbf_poll.poll_tbf = tbf;
+ return pdch_ulc_add_node(ulc, item);
}
int pdch_ulc_reserve_sba(struct pdch_ulc *ulc, struct gprs_rlcmac_sba *sba)
@@ -147,6 +167,40 @@ int pdch_ulc_release_fn(struct pdch_ulc *ulc, uint32_t fn)
return 0;
}
+void pdch_ulc_release_tbf(struct pdch_ulc *ulc, const struct gprs_rlcmac_tbf *tbf)
+{
+ bool tree_modified;
+ do {
+ struct rb_node *node;
+ struct pdch_ulc_node *item;
+ const struct gprs_rlcmac_tbf *item_tbf;
+
+ tree_modified = false;
+ for (node = rb_first(&ulc->tree_root); node; node = rb_next(node)) {
+ item = container_of(node, struct pdch_ulc_node, node);
+ switch (item->type) {
+ case PDCH_ULC_NODE_SBA:
+ continue;
+ case PDCH_ULC_NODE_TBF_POLL:
+ item_tbf = item->tbf_poll.poll_tbf;
+ break;
+ case PDCH_ULC_NODE_TBF_USF:
+ item_tbf = (struct gprs_rlcmac_tbf *)item->tbf_usf.ul_tbf;
+ break;
+ }
+ if (item_tbf != tbf)
+ continue;
+ /* One entry found, remove it from tree and restart
+ * search from start (to avoid traverse continue from
+ * no-more existant node */
+ tree_modified = true;
+ rb_erase(&item->node, &ulc->tree_root);
+ talloc_free(item);
+ break;
+ }
+ } while (tree_modified);
+}
+
void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn)
{
struct gprs_rlcmac_sba *sba;
@@ -170,7 +224,10 @@ void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn)
/* TODO: increase N3...*/
break;
case PDCH_ULC_NODE_TBF_POLL:
- /* TODO: increase N3...*/
+ LOGPDCH(ulc->pdch, DRLCMAC, LOGL_NOTICE,
+ "Timeout for registered POLL (FN=%u): %s\n",
+ item->fn, tbf_name(item->tbf_poll.poll_tbf));
+ tbf_poll_timeout(item->tbf_poll.poll_tbf);
break;
case PDCH_ULC_NODE_SBA:
sba = item->sba.sba;
diff --git a/src/pdch_ul_controller.h b/src/pdch_ul_controller.h
index e86dbf52..53604a9f 100644
--- a/src/pdch_ul_controller.h
+++ b/src/pdch_ul_controller.h
@@ -70,10 +70,14 @@ int pdch_ulc_reserve_sba(struct pdch_ulc *ulc, struct gprs_rlcmac_sba *sba);
bool pdch_ulc_fn_is_free(struct pdch_ulc *ulc, uint32_t fn);
+int pdch_ulc_get_next_free_rrbp_fn(struct pdch_ulc *ulc, uint32_t fn, uint32_t *poll_fn, unsigned int *rrbp);
+
struct pdch_ulc_node *pdch_ulc_get_node(struct pdch_ulc *ulc, uint32_t fn);
struct pdch_ulc_node *pdch_ulc_pop_node(struct pdch_ulc *ulc, uint32_t fn);
struct gprs_rlcmac_sba *pdch_ulc_get_sba(struct pdch_ulc *ulc, uint32_t fn);
+void pdch_ulc_release_tbf(struct pdch_ulc *ulc, const struct gprs_rlcmac_tbf *tbf);
+
int pdch_ulc_release_fn(struct pdch_ulc *ulc, uint32_t fn);
void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn);
diff --git a/src/poll_controller.cpp b/src/poll_controller.cpp
deleted file mode 100644
index fe101718..00000000
--- a/src/poll_controller.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/* poll_controller.h
- *
- * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
- * 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 <poll_controller.h>
-#include <bts.h>
-#include <tbf.h>
-#include <tbf_ul.h>
-#include <tbf_dl.h>
-#include <cxx_linuxlist.h>
-#include <sba.h>
-
-extern "C" {
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/gsm/gsm_utils.h>
-}
-
-PollController::PollController(struct gprs_rlcmac_bts& bts)
- : m_bts(bts)
-{}
-
-static inline bool elapsed_fn_check(unsigned max_delay, int frame_number, uint32_t from)
-{
- uint32_t elapsed = (frame_number + GSM_MAX_FN - from) % GSM_MAX_FN;
-
- if (elapsed > max_delay && elapsed < 2715400)
- return true;
-
- return false;
-}
-
-void PollController::expireTimedout(int frame_number, unsigned max_delay)
-{
- struct gprs_rlcmac_dl_tbf *dl_tbf;
- struct gprs_rlcmac_ul_tbf *ul_tbf;
- struct llist_item *pos;
-
- llist_for_each_entry(pos, &m_bts.ul_tbfs, list) {
- ul_tbf = as_ul_tbf((struct gprs_rlcmac_tbf *)pos->entry);
- if (ul_tbf->poll_scheduled()) {
- if (elapsed_fn_check(max_delay, frame_number, ul_tbf->poll_fn))
- ul_tbf->poll_timeout();
- }
- }
- llist_for_each_entry(pos, &m_bts.dl_tbfs, list) {
- dl_tbf = as_dl_tbf((struct gprs_rlcmac_tbf *)pos->entry);
- if (dl_tbf->poll_scheduled()) {
- if (elapsed_fn_check(max_delay, frame_number, dl_tbf->poll_fn))
- dl_tbf->poll_timeout();
- }
- }
-}
diff --git a/src/poll_controller.h b/src/poll_controller.h
deleted file mode 100644
index 8e709a30..00000000
--- a/src/poll_controller.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* poll_controller.h
- *
- * 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/>.
- *
- */
-
-#pragma once
-
-struct gprs_rlcmac_bts;
-
-/**
- * I belong to a BTS and I am responsible for finding TBFs and
- * SBAs that should have been polled and execute the timeout
- * action on them.
- */
-struct PollController {
-public:
- PollController(struct gprs_rlcmac_bts& bts);
-
- /* check for poll timeout */
- void expireTimedout(int frame_number, unsigned max_delay);
-
-private:
- struct gprs_rlcmac_bts& m_bts;
-
-private:
- /* disable copying to avoid slicing */
- PollController(const PollController&);
- PollController& operator=(const PollController&);
-};
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 87ca5bd8..7237f583 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -550,8 +550,7 @@ void gprs_rlcmac_tbf::t_start(enum tbf_timers t, int T, const char *reason, bool
int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
uint32_t *poll_fn_, unsigned int *rrbp_) const
{
- uint32_t new_poll_fn = next_fn(fn, 13);
-
+ int rc;
if (!is_control_ts(ts)) {
LOGPTBF(this, LOGL_DEBUG, "Polling cannot be "
"scheduled in this TS %d (first control TS %d)\n",
@@ -562,15 +561,13 @@ int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
LOGPTBF(this, LOGL_DEBUG, "Polling is already scheduled\n");
return -EBUSY;
}
- if (!pdch_ulc_fn_is_free(trx->pdch[ts].ulc, new_poll_fn)) {
- LOGPTBF(this, LOGL_DEBUG, "Polling is already scheduled "
- "for single block allocation at FN %d TS %d ...\n",
- new_poll_fn, ts);
- return -EBUSY;
- }
- *poll_fn_ = new_poll_fn;
- *rrbp_ = 0;
+ if ((rc = pdch_ulc_get_next_free_rrbp_fn(trx->pdch[ts].ulc, fn, poll_fn_, rrbp_)) < 0) {
+ LOGPTBF(this, LOGL_DEBUG,
+ "(bts=%u,trx=%u,ts=%u) FN=%u No suitable free RRBP offset found!\n",
+ trx->bts->nr, trx->trx_no, ts, fn);
+ return rc;
+ }
return 0;
}
@@ -591,6 +588,11 @@ void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum gprs_rl
chan, new_poll_fn, ts);
/* schedule polling */
+ if (pdch_ulc_reserve_tbf_poll(trx->pdch[ts].ulc, new_poll_fn, this) < 0) {
+ LOGPTBFDL(this, LOGL_ERROR, "Failed scheduling poll on %s (FN=%d, TS=%d)\n",
+ chan, poll_fn, ts);
+ return;
+ }
poll_state = GPRS_RLCMAC_POLL_SCHED;
poll_fn = new_poll_fn;
poll_ts = ts;
@@ -1230,3 +1232,8 @@ void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t
{
return tbf->set_polling(new_poll_fn, ts, t);
}
+
+void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf)
+{
+ tbf->poll_timeout();
+}
diff --git a/src/tbf.h b/src/tbf.h
index 989ec083..779bc263 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -209,6 +209,7 @@ uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf);
int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts, uint32_t *poll_fn, unsigned int *rrbp);
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t);
+void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf);
#ifdef __cplusplus
}
#endif