Merge branch 'sysmocom/tbf-split'

We start to separate the UL and DL part of the TBF now as they
really behave differently. One works on RLCmac frames (plural)
and sends them, the other is just assembling one of them. The
code will become more clear now.
This commit is contained in:
Holger Hans Peter Freyther 2014-07-22 12:37:10 +02:00
commit 4bbe3349c2
6 changed files with 182 additions and 94 deletions

View File

@ -217,15 +217,15 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
} }
/* search for active downlink tbf */ /* search for active downlink tbf */
gprs_rlcmac_tbf *BTS::dl_tbf_by_tlli(uint32_t tlli) gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_tlli(uint32_t tlli)
{ {
return tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF); return static_cast<gprs_rlcmac_dl_tbf *>(tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF));
} }
/* search for active uplink tbf */ /* search for active uplink tbf */
gprs_rlcmac_tbf *BTS::ul_tbf_by_tlli(uint32_t tlli) gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tlli(uint32_t tlli)
{ {
return tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF); return static_cast<gprs_rlcmac_ul_tbf *>(tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF));
} }
/* search for active downlink or uplink tbf */ /* search for active downlink or uplink tbf */
@ -234,12 +234,14 @@ gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_tbf *tbf;
if (dir == GPRS_RLCMAC_UL_TBF) { if (dir == GPRS_RLCMAC_UL_TBF) {
llist_for_each_entry(tbf, &m_bts.ul_tbfs, list) { llist_for_each_entry(tbf, &m_bts.ul_tbfs, list) {
OSMO_ASSERT(tbf->direction == dir);
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->tlli() == tlli && tbf->is_tlli_valid()) && tbf->tlli() == tlli && tbf->is_tlli_valid())
return tbf; return tbf;
} }
} else { } else {
llist_for_each_entry(tbf, &m_bts.dl_tbfs, list) { llist_for_each_entry(tbf, &m_bts.dl_tbfs, list) {
OSMO_ASSERT(tbf->direction == dir);
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->tlli() == tlli) && tbf->tlli() == tlli)
return tbf; return tbf;
@ -248,9 +250,9 @@ gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction
return NULL; return NULL;
} }
gprs_rlcmac_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{ {
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_dl_tbf *tbf;
/* only one TBF can poll on specific TS/FN, because scheduler can only /* 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 */ * schedule one downlink control block (with polling) at a FN per TS */
@ -258,14 +260,16 @@ gprs_rlcmac_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx && tbf->poll_fn == fn && tbf->trx->trx_no == trx
&& tbf->control_ts == ts) && tbf->control_ts == ts) {
return tbf; OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_DL_TBF);
return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
}
} }
return NULL; return NULL;
} }
gprs_rlcmac_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{ {
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_ul_tbf *tbf;
/* only one TBF can poll on specific TS/FN, because scheduler can only /* 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 */ * schedule one downlink control block (with polling) at a FN per TS */
@ -273,22 +277,24 @@ gprs_rlcmac_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx && tbf->poll_fn == fn && tbf->trx->trx_no == trx
&& tbf->control_ts == ts) && tbf->control_ts == ts) {
return tbf; OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_UL_TBF);
return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
}
} }
return NULL; return NULL;
} }
/* lookup downlink TBF Entity (by TFI) */ /* lookup downlink TBF Entity (by TFI) */
gprs_rlcmac_tbf *BTS::dl_tbf_by_tfi(uint8_t tfi, uint8_t trx) gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_tfi(uint8_t tfi, uint8_t trx)
{ {
return tbf_by_tfi(tfi, trx, GPRS_RLCMAC_DL_TBF); return static_cast<gprs_rlcmac_dl_tbf *>(tbf_by_tfi(tfi, trx, GPRS_RLCMAC_DL_TBF));
} }
/* lookup uplink TBF Entity (by TFI) */ /* lookup uplink TBF Entity (by TFI) */
gprs_rlcmac_tbf *BTS::ul_tbf_by_tfi(uint8_t tfi, uint8_t trx) gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tfi(uint8_t tfi, uint8_t trx)
{ {
return tbf_by_tfi(tfi, trx, GPRS_RLCMAC_UL_TBF); return static_cast<gprs_rlcmac_ul_tbf *>(tbf_by_tfi(tfi, trx, GPRS_RLCMAC_UL_TBF));
} }
/* lookup TBF Entity (by TFI) */ /* lookup TBF Entity (by TFI) */
@ -307,8 +313,10 @@ gprs_rlcmac_tbf *BTS::tbf_by_tfi(uint8_t tfi, uint8_t trx,
if (!tbf) if (!tbf)
return NULL; return NULL;
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) {
OSMO_ASSERT(tbf->direction == dir);
return tbf; return tbf;
}
return NULL; return NULL;
} }
@ -409,7 +417,7 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
{ {
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_ul_tbf *tbf;
uint8_t trx_no, ts_no = 0; uint8_t trx_no, ts_no = 0;
int8_t tfi; /* must be signed */ int8_t tfi; /* must be signed */
uint8_t sb = 0; uint8_t sb = 0;
@ -453,7 +461,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
return -EBUSY; return -EBUSY;
} }
/* set class to 0, since we don't know the multislot class yet */ /* set class to 0, since we don't know the multislot class yet */
tbf = tbf_alloc(&m_bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, 0, 1); tbf = tbf_alloc_ul_tbf(&m_bts, NULL, tfi, trx_no, 0, 1);
if (!tbf) { if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
/* FIXME: send reject */ /* FIXME: send reject */
@ -684,7 +692,7 @@ void gprs_rlcmac_pdch::add_paging(struct gprs_rlcmac_paging *pag)
*/ */
int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, int8_t rssi) int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, int8_t rssi)
{ {
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_ul_tbf *tbf;
struct rlc_ul_header *rh = (struct rlc_ul_header *)data; struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
switch (len) { switch (len) {
@ -859,24 +867,24 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn) void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn)
{ {
struct gprs_rlcmac_tbf *tbf;
struct gprs_rlcmac_sba *sba; struct gprs_rlcmac_sba *sba;
int rc; int rc;
if (request->ID.UnionType) { if (request->ID.UnionType) {
struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_dl_tbf *dl_tbf;
uint32_t tlli = request->ID.u.TLLI; uint32_t tlli = request->ID.u.TLLI;
uint8_t ms_class = 0; uint8_t ms_class = 0;
struct gprs_rlcmac_tbf *dl_tbf;
uint8_t ta; uint8_t ta;
tbf = bts()->ul_tbf_by_tlli(tlli); ul_tbf = bts()->ul_tbf_by_tlli(tlli);
if (tbf) { if (ul_tbf) {
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from " LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still " "TLLI=0x%08x while %s still "
"exists. Killing pending DL TBF\n", "exists. Killing pending DL TBF\n",
tlli, tbf_name(tbf)); tlli, tbf_name(ul_tbf));
tbf_free(tbf); tbf_free(ul_tbf);
tbf = NULL; ul_tbf = NULL;
} }
if ((dl_tbf = bts()->dl_tbf_by_tlli(tlli))) { if ((dl_tbf = bts()->dl_tbf_by_tlli(tlli))) {
@ -910,34 +918,41 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request,
ms_class = Decoding::get_ms_class_by_capability(&request->MS_Radio_Access_capability); ms_class = Decoding::get_ms_class_by_capability(&request->MS_Radio_Access_capability);
if (!ms_class) if (!ms_class)
LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n"); LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
tbf = tbf_alloc_ul(bts_data(), trx_no(), ms_class, tlli, ta, NULL); ul_tbf = tbf_alloc_ul(bts_data(), trx_no(), ms_class, tlli, ta, NULL);
if (!tbf) if (!ul_tbf)
return; return;
/* set control ts to current MS's TS, until assignment complete */ /* set control ts to current MS's TS, until assignment complete */
LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts_no); LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts_no);
tbf->control_ts = ts_no; ul_tbf->control_ts = ts_no;
/* schedule uplink assignment */ /* schedule uplink assignment */
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; ul_tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
return; return;
} }
if (request->ID.u.Global_TFI.UnionType) { if (request->ID.u.Global_TFI.UnionType) {
struct gprs_rlcmac_dl_tbf *dl_tbf;
int8_t tfi = request->ID.u.Global_TFI.u.DOWNLINK_TFI; int8_t tfi = request->ID.u.Global_TFI.u.DOWNLINK_TFI;
tbf = bts()->dl_tbf_by_tfi(tfi, trx_no()); dl_tbf = bts()->dl_tbf_by_tfi(tfi, trx_no());
if (!tbf) { if (!dl_tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TFI=%d\n", tfi); LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TFI=%d\n", tfi);
return; return;
} }
LOGP(DRLCMAC, LOGL_ERROR,
"RX: [PCU <- BTS] %s FIXME: Packet resource request\n",
tbf_name(dl_tbf));
} else { } else {
struct gprs_rlcmac_ul_tbf *ul_tbf;
int8_t tfi = request->ID.u.Global_TFI.u.UPLINK_TFI; int8_t tfi = request->ID.u.Global_TFI.u.UPLINK_TFI;
tbf = bts()->ul_tbf_by_tfi(tfi, trx_no()); ul_tbf = bts()->ul_tbf_by_tfi(tfi, trx_no());
if (!tbf) { if (!ul_tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TFI=%d\n", tfi); LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TFI=%d\n", tfi);
return; return;
} }
LOGP(DRLCMAC, LOGL_ERROR,
"RX: [PCU <- BTS] %s FIXME: Packet resource request\n",
tbf_name(ul_tbf));
} }
LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s FIXME: Packet resource request\n", tbf_name(tbf));
} }
void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *report, uint32_t fn) void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *report, uint32_t fn)
@ -1023,11 +1038,13 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t
return rc; return rc;
} }
gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi) gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir)
{ {
gprs_rlcmac_tbf *tbf; gprs_rlcmac_tbf *tbf;
llist_for_each_entry(tbf, tbf_list, list) { llist_for_each_entry(tbf, tbf_list, list) {
OSMO_ASSERT(tbf->direction == dir);
if (tbf->tfi() != tfi) if (tbf->tfi() != tfi)
continue; continue;
if (!tbf->pdch[ts_no]) if (!tbf->pdch[ts_no])
@ -1037,12 +1054,12 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l
return NULL; return NULL;
} }
gprs_rlcmac_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi) gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi)
{ {
return tbf_from_list_by_tfi(&bts_data()->ul_tbfs, tfi); return static_cast<gprs_rlcmac_ul_tbf *>(tbf_from_list_by_tfi(&bts_data()->ul_tbfs, tfi, GPRS_RLCMAC_UL_TBF));
} }
gprs_rlcmac_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi) gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi)
{ {
return tbf_from_list_by_tfi(&bts_data()->dl_tbfs, tfi); return static_cast<gprs_rlcmac_dl_tbf *>(tbf_from_list_by_tfi(&bts_data()->dl_tbfs, tfi, GPRS_RLCMAC_DL_TBF));
} }

View File

@ -62,8 +62,8 @@ struct gprs_rlcmac_pdch {
BTS *bts() const; BTS *bts() const;
uint8_t trx_no() const; uint8_t trx_no() const;
struct gprs_rlcmac_tbf *ul_tbf_by_tfi(uint8_t tfi); struct gprs_rlcmac_ul_tbf *ul_tbf_by_tfi(uint8_t tfi);
struct gprs_rlcmac_tbf *dl_tbf_by_tfi(uint8_t tfi); struct gprs_rlcmac_dl_tbf *dl_tbf_by_tfi(uint8_t tfi);
#endif #endif
uint8_t m_is_enabled; /* TS is enabled */ uint8_t m_is_enabled; /* TS is enabled */
@ -87,7 +87,8 @@ private:
void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn); void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn);
void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn); void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn);
void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn); void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn);
gprs_rlcmac_tbf *tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi); gprs_rlcmac_tbf *tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir);
#endif #endif
}; };
@ -192,12 +193,12 @@ public:
/** add paging to paging queue(s) */ /** add paging to paging queue(s) */
int add_paging(uint8_t chan_needed, uint8_t *identity_lv); int add_paging(uint8_t chan_needed, uint8_t *identity_lv);
gprs_rlcmac_tbf *dl_tbf_by_tlli(uint32_t tlli); gprs_rlcmac_dl_tbf *dl_tbf_by_tlli(uint32_t tlli);
gprs_rlcmac_tbf *ul_tbf_by_tlli(uint32_t tlli); gprs_rlcmac_ul_tbf *ul_tbf_by_tlli(uint32_t tlli);
gprs_rlcmac_tbf *dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts); gprs_rlcmac_dl_tbf *dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts);
gprs_rlcmac_tbf *ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts); gprs_rlcmac_ul_tbf *ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts);
gprs_rlcmac_tbf *dl_tbf_by_tfi(uint8_t tfi, uint8_t trx); gprs_rlcmac_dl_tbf *dl_tbf_by_tfi(uint8_t tfi, uint8_t trx);
gprs_rlcmac_tbf *ul_tbf_by_tfi(uint8_t tfi, uint8_t trx); gprs_rlcmac_ul_tbf *ul_tbf_by_tfi(uint8_t tfi, uint8_t trx);
int tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx); int tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx);

View File

@ -165,7 +165,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
return -EBUSY; return -EBUSY;
} }
/* set number of downlink slots according to multislot class */ /* set number of downlink slots according to multislot class */
tbf = tbf_alloc(bts, tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class, ss); tbf = tbf_alloc_dl_tbf(bts, tbf, tfi, trx, ms_class, ss);
if (!tbf) { if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
/* FIXME: send reject */ /* FIXME: send reject */
@ -214,12 +214,12 @@ int gprs_rlcmac_tbf::handle(struct gprs_rlcmac_bts *bts,
return tbf_new_dl_assignment(bts, imsi, tlli, ms_class, data, len); return tbf_new_dl_assignment(bts, imsi, tlli, ms_class, data, len);
} }
struct gprs_rlcmac_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
int8_t use_trx, uint8_t ms_class, int8_t use_trx, uint8_t ms_class,
uint32_t tlli, uint8_t ta, struct gprs_rlcmac_tbf *dl_tbf) uint32_t tlli, uint8_t ta, struct gprs_rlcmac_tbf *dl_tbf)
{ {
uint8_t trx; uint8_t trx;
struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_ul_tbf *tbf;
int8_t tfi; /* must be signed */ int8_t tfi; /* must be signed */
#warning "Copy and paste with tbf_new_dl_assignment" #warning "Copy and paste with tbf_new_dl_assignment"
@ -231,7 +231,7 @@ struct gprs_rlcmac_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
return NULL; return NULL;
} }
/* use multislot class of downlink TBF */ /* use multislot class of downlink TBF */
tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx, ms_class, 0); tbf = tbf_alloc_ul_tbf(bts, dl_tbf, tfi, trx, ms_class, 0);
if (!tbf) { if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
/* FIXME: send reject */ /* FIXME: send reject */
@ -479,29 +479,20 @@ void gprs_rlcmac_tbf::poll_timeout()
LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n"); LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
} }
struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, static int setup_tbf(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf, enum gprs_rlcmac_tbf_direction dir, struct gprs_rlcmac_tbf *old_tbf, uint8_t tfi, uint8_t trx,
uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot) uint8_t ms_class, uint8_t single_slot)
{ {
struct gprs_rlcmac_tbf *tbf;
int rc; int rc;
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
"MS_CLASS=%d\n", (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
tfi, trx, ms_class);
if (trx >= 8 || tfi >= 32) if (trx >= 8 || tfi >= 32)
return NULL; return -1;
tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_tbf);
if (!tbf) if (!tbf)
return NULL; return -1;
tbf->m_created_ts = time(NULL); tbf->m_created_ts = time(NULL);
tbf->bts = bts->bts; tbf->bts = bts->bts;
tbf->direction = dir;
tbf->m_tfi = tfi; tbf->m_tfi = tfi;
tbf->trx = &bts->trx[trx]; tbf->trx = &bts->trx[trx];
tbf->ms_class = ms_class; tbf->ms_class = ms_class;
@ -510,16 +501,14 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts,
single_slot); single_slot);
/* if no resource */ /* if no resource */
if (rc < 0) { if (rc < 0) {
talloc_free(tbf); return -1;
return NULL;
} }
/* assign control ts */ /* assign control ts */
tbf->control_ts = 0xff; tbf->control_ts = 0xff;
rc = tbf_assign_control_ts(tbf); rc = tbf_assign_control_ts(tbf);
/* if no resource */ /* if no resource */
if (rc < 0) { if (rc < 0) {
talloc_free(tbf); return -1;
return NULL;
} }
/* set timestamp */ /* set timestamp */
@ -528,14 +517,73 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts,
gettimeofday(&tbf->meas.dl_loss_tv, NULL); gettimeofday(&tbf->meas.dl_loss_tv, NULL);
tbf->m_llc.init(); tbf->m_llc.init();
if (dir == GPRS_RLCMAC_UL_TBF) { return 0;
llist_add(&tbf->list, &bts->ul_tbfs); }
tbf->bts->tbf_ul_created();
} else {
llist_add(&tbf->list, &bts->dl_tbfs); struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
tbf->bts->tbf_dl_created(); struct gprs_rlcmac_tbf *old_tbf, uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot)
{
struct gprs_rlcmac_ul_tbf *tbf;
int rc;
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
"MS_CLASS=%d\n", "UL", tfi, trx, ms_class);
if (trx >= 8 || tfi >= 32)
return NULL;
tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
if (!tbf)
return NULL;
tbf->direction = GPRS_RLCMAC_UL_TBF;
rc = setup_tbf(tbf, bts, old_tbf, tfi, trx, ms_class, single_slot);
/* if no resource */
if (rc < 0) {
talloc_free(tbf);
return NULL;
} }
llist_add(&tbf->list, &bts->ul_tbfs);
tbf->bts->tbf_ul_created();
return tbf;
}
struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf, uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot)
{
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
"MS_CLASS=%d\n", "DL", tfi, trx, ms_class);
if (trx >= 8 || tfi >= 32)
return NULL;
tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
if (!tbf)
return NULL;
tbf->direction = GPRS_RLCMAC_DL_TBF;
rc = setup_tbf(tbf, bts, old_tbf, tfi, trx, ms_class, single_slot);
/* if no resource */
if (rc < 0) {
talloc_free(tbf);
return NULL;
}
llist_add(&tbf->list, &bts->dl_tbfs);
tbf->bts->tbf_dl_created();
return tbf; return tbf;
} }

View File

@ -259,13 +259,18 @@ protected:
}; };
struct gprs_rlcmac_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
int8_t use_trx, uint8_t ms_class, int8_t use_trx, uint8_t ms_class,
uint32_t tlli, uint8_t ta, struct gprs_rlcmac_tbf *dl_tbf); uint32_t tlli, uint8_t ta, struct gprs_rlcmac_tbf *dl_tbf);
struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *old_tbf,
enum gprs_rlcmac_tbf_direction dir, uint8_t tfi, uint8_t trx, uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot);
struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf,
uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot); uint8_t ms_class, uint8_t single_slot);
void tbf_free(struct gprs_rlcmac_tbf *tbf); void tbf_free(struct gprs_rlcmac_tbf *tbf);
@ -326,6 +331,12 @@ inline time_t gprs_rlcmac_tbf::created_ts() const
return m_created_ts; return m_created_ts;
} }
struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
};
struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
};
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -36,6 +36,17 @@ extern "C" {
void *tall_pcu_ctx; void *tall_pcu_ctx;
int16_t spoof_mnc = 0, spoof_mcc = 0; int16_t spoof_mnc = 0, spoof_mcc = 0;
static gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf, gprs_rlcmac_tbf_direction dir,
uint8_t tfi, uint8_t trx,
uint8_t ms_class, uint8_t single_slot)
{
if (dir == GPRS_RLCMAC_UL_TBF)
return tbf_alloc_ul_tbf(bts, old_tbf, tfi, trx, ms_class, single_slot);
else
return tbf_alloc_dl_tbf(bts, old_tbf, tfi, trx, ms_class, single_slot);
}
static void test_alloc_a(gprs_rlcmac_tbf_direction dir, const int count) static void test_alloc_a(gprs_rlcmac_tbf_direction dir, const int count)
{ {
int tfi; int tfi;
@ -136,14 +147,14 @@ static void test_alloc_b(int ms_class)
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 1); ul_tbf = tbf_alloc_ul_tbf(bts, NULL, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(ul_tbf); OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL"); dump_assignment(ul_tbf, "UL");
/* assume final ack has not been sent */ /* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0); dl_tbf = tbf_alloc_dl_tbf(bts, ul_tbf, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf); OSMO_ASSERT(dl_tbf);
dump_assignment(dl_tbf, "DL"); dump_assignment(dl_tbf, "DL");
@ -177,7 +188,7 @@ static void test_alloc_b(int ms_class)
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 1); dl_tbf = tbf_alloc_dl_tbf(bts, NULL, tfi, trx_no, ms_class, 1);
dl_tbf->m_tlli = 0x23; dl_tbf->m_tlli = 0x23;
dl_tbf->m_tlli_valid = true; dl_tbf->m_tlli_valid = true;
OSMO_ASSERT(dl_tbf); OSMO_ASSERT(dl_tbf);
@ -185,7 +196,7 @@ static void test_alloc_b(int ms_class)
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0); ul_tbf = tbf_alloc_ul_tbf(bts, dl_tbf, tfi, trx_no, ms_class, 0);
ul_tbf->m_tlli = 0x23; ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true; ul_tbf->m_tlli_valid = true;
ul_tbf->dir.ul.contention_resolution_done = 1; ul_tbf->dir.ul.contention_resolution_done = 1;
@ -226,14 +237,14 @@ static void test_alloc_b(int ms_class)
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0); ul_tbf = tbf_alloc_ul_tbf(bts, NULL, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(ul_tbf); OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL"); dump_assignment(ul_tbf, "UL");
/* assume final ack has not been sent */ /* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0); dl_tbf = tbf_alloc_dl_tbf(bts, ul_tbf, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf); OSMO_ASSERT(dl_tbf);
dump_assignment(dl_tbf, "DL"); dump_assignment(dl_tbf, "DL");
@ -290,13 +301,13 @@ static void test_alloc_b(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 1); ul_tbf = tbf_alloc_ul_tbf(bts, NULL, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(ul_tbf); OSMO_ASSERT(ul_tbf);
/* assume final ack has not been sent */ /* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0); dl_tbf = tbf_alloc_dl_tbf(bts, ul_tbf, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf); OSMO_ASSERT(dl_tbf);
/* verify that both are on the same ts */ /* verify that both are on the same ts */
@ -333,14 +344,14 @@ static void test_alloc_b(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 1); dl_tbf = tbf_alloc_dl_tbf(bts, NULL, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(dl_tbf); OSMO_ASSERT(dl_tbf);
dl_tbf->m_tlli = 0x23; dl_tbf->m_tlli = 0x23;
dl_tbf->m_tlli_valid = true; dl_tbf->m_tlli_valid = true;
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0); OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0); ul_tbf = tbf_alloc_ul_tbf(bts, dl_tbf, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(ul_tbf); OSMO_ASSERT(ul_tbf);
ul_tbf->m_tlli = 0x23; ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true; ul_tbf->m_tlli_valid = true;

View File

@ -44,16 +44,16 @@ static void test_tbf_tlli_update()
/* /*
* Make a uplink and downlink allocation * Make a uplink and downlink allocation
*/ */
gprs_rlcmac_tbf *dl_tbf = tbf_alloc(the_bts.bts_data(), gprs_rlcmac_tbf *dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(),
NULL, GPRS_RLCMAC_DL_TBF, 0, NULL, 0,
0, 0, 0); 0, 0, 0);
dl_tbf->update_tlli(0x2342); dl_tbf->update_tlli(0x2342);
dl_tbf->tlli_mark_valid(); dl_tbf->tlli_mark_valid();
dl_tbf->ta = 4; dl_tbf->ta = 4;
the_bts.timing_advance()->remember(0x2342, dl_tbf->ta); the_bts.timing_advance()->remember(0x2342, dl_tbf->ta);
gprs_rlcmac_tbf *ul_tbf = tbf_alloc(the_bts.bts_data(), gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(the_bts.bts_data(),
ul_tbf, GPRS_RLCMAC_UL_TBF, 0, ul_tbf, 0,
0, 0, 0); 0, 0, 0);
ul_tbf->update_tlli(0x2342); ul_tbf->update_tlli(0x2342);
ul_tbf->tlli_mark_valid(); ul_tbf->tlli_mark_valid();