diff options
Diffstat (limited to 'src/bts.cpp')
-rw-r--r-- | src/bts.cpp | 286 |
1 files changed, 226 insertions, 60 deletions
diff --git a/src/bts.cpp b/src/bts.cpp index d1d738c6..715fb515 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -52,11 +52,14 @@ static BTS s_bts; static const struct rate_ctr_desc bts_ctr_description[] = { { "tbf.dl.alloc", "TBF DL Allocated "}, { "tbf.dl.freed", "TBF DL Freed "}, + { "tbf.dl.aborted", "TBF DL Aborted "}, { "tbf.ul.alloc", "TBF UL Allocated "}, { "tbf.ul.freed", "TBF UL Freed "}, + { "tbf.ul.aborted", "TBF UL Aborted "}, { "tbf.reused", "TBF Reused "}, { "tbf.alloc.algo-a", "TBF Alloc Algo A "}, { "tbf.alloc.algo-b", "TBF Alloc Algo B "}, + { "tbf.failed.egprs-only", "TBF Failed EGPRS-only"}, { "rlc.sent", "RLC Sent "}, { "rlc.resent", "RLC Resent "}, { "rlc.restarted", "RLC Restarted "}, @@ -127,8 +130,6 @@ BTS::BTS() , m_ms_store(this) { memset(&m_bts, 0, sizeof(m_bts)); - INIT_LLIST_HEAD(&m_bts.ul_tbfs); - INIT_LLIST_HEAD(&m_bts.dl_tbfs); m_bts.bts = this; /* initialize back pointers */ @@ -214,14 +215,14 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv) { uint8_t l, trx, ts, any_tbf = 0; struct gprs_rlcmac_tbf *tbf; - struct llist_pods *lpods; + LListHead<gprs_rlcmac_tbf> *pos; struct gprs_rlcmac_paging *pag; uint8_t slot_mask[8]; int8_t first_ts; /* must be signed */ - llist_head *tbfs_lists[] = { - &m_bts.ul_tbfs, - &m_bts.dl_tbfs, + LListHead<gprs_rlcmac_tbf> *tbfs_lists[] = { + &m_ul_tbfs, + &m_dl_tbfs, NULL }; @@ -235,7 +236,8 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv) * Don't mark, if TBF uses a different slot that is already marked. */ memset(slot_mask, 0, sizeof(slot_mask)); for (l = 0; tbfs_lists[l]; l++) { - llist_pods_for_each_entry(tbf, tbfs_lists[l], list, lpods) { + llist_for_each(pos, tbfs_lists[l]) { + tbf = pos->entry(); first_ts = -1; for (ts = 0; ts < 8; ts++) { if (tbf->pdch[ts]) { @@ -296,16 +298,17 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv) gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) { struct gprs_rlcmac_dl_tbf *tbf; - struct llist_pods *lpods; + LListHead<gprs_rlcmac_tbf> *pos; /* 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_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) { + llist_for_each(pos, &m_dl_tbfs) { + tbf = as_dl_tbf(pos->entry()); if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_fn == fn && tbf->trx->trx_no == trx - && tbf->control_ts == ts) { - return static_cast<gprs_rlcmac_dl_tbf *>(tbf); + && tbf->poll_ts == ts) { + return tbf; } } return NULL; @@ -313,16 +316,17 @@ gprs_rlcmac_dl_tbf *BTS::dl_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_ul_tbf *tbf; - struct llist_pods *lpods; + LListHead<gprs_rlcmac_tbf> *pos; /* 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_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) { + llist_for_each(pos, &m_ul_tbfs) { + tbf = as_ul_tbf(pos->entry()); if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_fn == fn && tbf->trx->trx_no == trx - && tbf->control_ts == ts) { - return static_cast<gprs_rlcmac_ul_tbf *>(tbf); + && tbf->poll_ts == ts) { + return tbf; } } return NULL; @@ -462,7 +466,10 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) uint8_t sb = 0; uint32_t sb_fn = 0; int rc; - uint8_t plen; + int plen; + uint8_t usf = 7; + uint8_t tsc; + uint16_t ta; rach_frame(); @@ -481,8 +488,11 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) qta = 0; if (qta > 252) qta = 252; + + ta = qta >> 2; + if (sb) { - rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, qta >> 2); + rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, ta); if (rc < 0) return rc; LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d " @@ -492,6 +502,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) sb_fn); LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink " "(AGCH)\n"); + tsc = m_bts.trx[trx_no].pdch[ts_no].tsc; } else { // Create new TBF #warning "Copy and pate with other routines.." @@ -502,7 +513,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) /* FIXME: send reject */ return -EBUSY; } - tbf->set_ta(qta >> 2); + tbf->set_ta(ta); tbf->set_state(GPRS_RLCMAC_FLOW); tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); tbf_timer_start(tbf, 3169, m_bts.t3169, 0); @@ -514,21 +525,31 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26); LOGP(DRLCMAC, LOGL_INFO, "%s TX: START Immediate " "Assignment Uplink (AGCH)\n", tbf_name(tbf)); + trx_no = tbf->trx->trx_no; + ts_no = tbf->first_ts; + usf = tbf->m_usf[ts_no]; + tsc = tbf->tsc(); } bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */; bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); - if (sb) - plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra, - Fn, qta >> 2, m_bts.trx[trx_no].arfcn, ts_no, - m_bts.trx[trx_no].pdch[ts_no].tsc, 0, 0, 0, 0, sb_fn, 1, - m_bts.alpha, m_bts.gamma, -1); - else - plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra, - Fn, tbf->ta(), tbf->trx->arfcn, tbf->first_ts, tbf->tsc(), - tbf->tfi(), tbf->m_usf[tbf->first_ts], 0, 0, 0, 0, - m_bts.alpha, m_bts.gamma, -1); - pcu_l1if_tx_agch(immediate_assignment, plen); + + LOGP(DRLCMAC, LOGL_DEBUG, + " - TRX=%d (%d) TS=%d TA=%d TSC=%d TFI=%d USF=%d\n", + trx_no, m_bts.trx[trx_no].arfcn, ts_no, ta, tsc, + tbf ? tbf->tfi() : -1, usf); + + plen = Encoding::write_immediate_assignment( + tbf, immediate_assignment, 0, ra, Fn, ta, + m_bts.trx[trx_no].arfcn, ts_no, tsc, usf, 0, sb_fn, + m_bts.alpha, m_bts.gamma, -1); + + if (plen >= 0) { + pcu_l1if_tx_agch(immediate_assignment, plen); + if (tbf) + tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN); + } + bitvec_free(immediate_assignment); return 0; @@ -552,7 +573,8 @@ void BTS::trigger_dl_ass( /* change state */ dl_tbf->set_state(GPRS_RLCMAC_ASSIGN); - dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); + if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) + dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); /* start timer */ tbf_timer_start(dl_tbf, 0, Tassign_pacch); } else { @@ -570,17 +592,24 @@ void BTS::trigger_dl_ass( void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi) { int plen; + unsigned int ts = tbf->first_ts; LOGP(DRLCMAC, LOGL_INFO, "TX: START %s Immediate Assignment Downlink (PCH)\n", tbf_name(tbf)); bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */ bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); /* use request reference that has maximum distance to current time, * so the assignment will not conflict with possible RACH requests. */ - plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 1, 125, - (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta(), - tbf->trx->arfcn, tbf->first_ts, tbf->tsc(), tbf->tfi(), 0, tbf->tlli(), poll, - tbf->poll_fn, 0, m_bts.alpha, m_bts.gamma, -1); - pcu_l1if_tx_pch(immediate_assignment, plen, imsi); + LOGP(DRLCMAC, LOGL_DEBUG, " - TRX=%d (%d) TS=%d TA=%d pollFN=%d\n", + tbf->trx->trx_no, tbf->trx->arfcn, + ts, tbf->ta(), poll ? tbf->poll_fn : -1); + plen = Encoding::write_immediate_assignment(tbf, immediate_assignment, 1, 125, + (tbf->pdch[ts]->last_rts_fn + 21216) % 2715648, tbf->ta(), + tbf->trx->arfcn, ts, tbf->tsc(), 7, poll, + tbf->poll_fn, m_bts.alpha, m_bts.gamma, -1); + if (plen >= 0) { + pcu_l1if_tx_pch(immediate_assignment, plen, imsi); + tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN); + } bitvec_free(immediate_assignment); } @@ -775,9 +804,19 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, "TBF is gone TLLI=0x%08x\n", tlli); return; } - if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE)) + if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) && + tbf->direction == new_tbf->direction) tbf_free(tbf); + if ((new_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { + /* We now know that the PACCH really existed */ + LOGP(DRLCMAC, LOGL_INFO, + "The TBF has been confirmed on the PACCH, " + "changed type from CCCH to PACCH for %s\n", + tbf_name(new_tbf)); + new_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); + new_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); + } new_tbf->set_state(GPRS_RLCMAC_FLOW); /* stop pending assignment timer */ new_tbf->stop_timer(); @@ -803,7 +842,8 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, "TBF is gone TLLI=0x%08x\n", tlli); return; } - if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE)) + if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) && + tbf->direction == new_tbf->direction) tbf_free(tbf); new_tbf->set_state(GPRS_RLCMAC_FLOW); @@ -891,6 +931,11 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n struct gprs_rlcmac_dl_tbf *tbf; int rc; struct pcu_l1_meas meas; + int num_blocks; + uint8_t bits_data[RLC_GPRS_WS/8]; + bitvec bits; + int bsn_begin, bsn_end; + char show_bits[RLC_GPRS_WS + 1]; tfi = ack_nack->DOWNLINK_TFI; tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no); @@ -917,10 +962,24 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf)); tbf->poll_state = GPRS_RLCMAC_POLL_NONE; + bits.data = bits_data; + bits.data_len = sizeof(bits_data); + bits.cur_bit = 0; + + num_blocks = Decoding::decode_gprs_acknack_bits( + &ack_nack->Ack_Nack_Description, &bits, + &bsn_begin, &bsn_end, &tbf->m_window); + + LOGP(DRLCMAC, LOGL_DEBUG, + "Got GPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), " + "\"%s\"\n", + ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER, + bsn_begin, bsn_end, num_blocks, + (Decoding::extract_rbb(&bits, show_bits), show_bits)); + rc = tbf->rcvd_dl_ack( ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION, - ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER, - ack_nack->Ack_Nack_Description.RECEIVED_BLOCK_BITMAP); + bsn_begin, &bits); if (rc == 1) { tbf_free(tbf); return; @@ -945,6 +1004,112 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n } } +void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nack, uint32_t fn) +{ + int8_t tfi = 0; /* must be signed */ + struct gprs_rlcmac_dl_tbf *tbf; + struct pcu_l1_meas meas; + int rc; + int num_blocks; + uint8_t bits_data[RLC_EGPRS_MAX_WS/8]; + char show_bits[RLC_EGPRS_MAX_WS + 1]; + bitvec bits; + int bsn_begin, bsn_end; + + tfi = ack_nack->DOWNLINK_TFI; + tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no); + if (!tbf) { + LOGP(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; + } + if (tbf->tfi() != tfi) { + LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with " + "wrong TFI=%d, ignoring!\n", tfi); + return; + } + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK); + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) { + tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); + LOGP(DRLCMAC, LOGL_NOTICE, "Recovered EGPRS downlink ack " + "for %s\n", tbf_name(tbf)); + } + /* reset N3105 */ + tbf->n3105 = 0; + tbf->stop_t3191(); + LOGP(DRLCMAC, LOGL_DEBUG, + "RX: [PCU <- BTS] %s EGPRS Packet Downlink Ack/Nack\n", + tbf_name(tbf)); + tbf->poll_state = GPRS_RLCMAC_POLL_NONE; + + LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS ACK/NACK: " + "ut: %d, final: %d, bow: %d, eow: %d, ssn: %d, have_crbb: %d, " + "urbb_len:%d, %p, %p, %d, %d, win: %d-%d, urbb: %s\n", + (int)ack_nack->EGPRS_AckNack.UnionType, + (int)ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION, + (int)ack_nack->EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW, + (int)ack_nack->EGPRS_AckNack.Desc.END_OF_WINDOW, + (int)ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER, + (int)ack_nack->EGPRS_AckNack.Desc.Exist_CRBB, + (int)ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH, + (void *)&ack_nack->EGPRS_AckNack.UnionType, + (void *)&ack_nack->EGPRS_AckNack.Desc, + (int)offsetof(EGPRS_AckNack_t, Desc), + (int)offsetof(EGPRS_AckNack_w_len_t, Desc), + tbf->m_window.v_a(), + tbf->m_window.v_s(), + osmo_hexdump((const uint8_t *)&ack_nack->EGPRS_AckNack.Desc.URBB, + sizeof(ack_nack->EGPRS_AckNack.Desc.URBB))); + + bits.data = bits_data; + bits.data_len = sizeof(bits_data); + bits.cur_bit = 0; + + num_blocks = Decoding::decode_egprs_acknack_bits( + &ack_nack->EGPRS_AckNack.Desc, &bits, + &bsn_begin, &bsn_end, &tbf->m_window); + + LOGP(DRLCMAC, LOGL_DEBUG, + "Got EGPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), " + "\"%s\"\n", + ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER, + bsn_begin, bsn_end, num_blocks, + (Decoding::extract_rbb(&bits, show_bits), show_bits) + ); + + rc = tbf->rcvd_dl_ack( + ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION, + bsn_begin, &bits); + if (rc == 1) { + tbf_free(tbf); + return; + } + + /* check for channel request */ + if (ack_nack->Exist_ChannelRequestDescription) { + LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack " + "message, so we provide one:\n"); + + /* This call will register the new TBF with the MS on success */ + tbf_alloc_ul(bts_data(), tbf->trx->trx_no, + tbf->ms_class(), tbf->ms()->egprs_ms_class(), + tbf->tlli(), tbf->ta(), tbf->ms()); + + /* schedule uplink assignment */ + tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; + } + + /* get measurements */ + if (tbf->ms()) { + /* TODO: Implement Measurements parsing for EGPRS */ + /* + get_meas(&meas, &ack_nack->Channel_Quality_Report); + tbf->ms()->update_l1_meas(&meas); + */ + } +} + void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn) { struct gprs_rlcmac_sba *sba; @@ -968,28 +1133,24 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, ta = ms->ta(); } + /* We got a RACH so the MS was in packet idle mode and thus + * didn't have any active TBFs */ if (ul_tbf) { LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from " "TLLI=0x%08x while %s still " "exists. Killing pending UL TBF\n", tlli, tbf_name(ul_tbf)); - /* The MS will not use the old TBF again, so we can - * safely throw it away immediately */ tbf_free(ul_tbf); ul_tbf = NULL; } if (dl_tbf) { - /* TODO: There a chance that releasing dl_tbf can be - * avoided if this PDCH is the control TS of dl_tbf, - * but this needs to be checked with the spec. If an MS - * losed the DL TBF because of PDCH mismatches only, - * this check would make sense. */ LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from " "TLLI=0x%08x while %s still exists. " "Release pending DL TBF\n", tlli, tbf_name(dl_tbf)); - dl_tbf->release(); + tbf_free(dl_tbf); + dl_tbf = NULL; } LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF " "in packet resource request of single " @@ -1104,6 +1265,9 @@ int gprs_rlcmac_pdch::rcv_control_block( case MT_PACKET_DOWNLINK_ACK_NACK: rcv_control_dl_ack_nack(&ul_control_block->u.Packet_Downlink_Ack_Nack, fn); break; + case MT_EGPRS_PACKET_DOWNLINK_ACK_NACK: + rcv_control_egprs_dl_ack_nack(&ul_control_block->u.Egprs_Packet_Downlink_Ack_Nack, fn); + break; case MT_PACKET_RESOURCE_REQUEST: rcv_resource_request(&ul_control_block->u.Packet_Resource_Request, fn); break; @@ -1137,7 +1301,7 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, } LOGP(DRLCMACUL, LOGL_DEBUG, "Got RLC block, coding scheme: %s, " - "length: %d (%d))\n", cs.name(), len, cs.maxBytesUL()); + "length: %d (%d))\n", cs.name(), len, cs.usedSizeUL()); if (cs.isGprs()) return rcv_block_gprs(data, fn, meas, cs); @@ -1155,9 +1319,9 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn, struct pcu_l1_meas *meas, GprsCodingScheme cs) { int rc; - struct gprs_rlc_ul_header_egprs rlc_dec; + struct gprs_rlc_data_info rlc_dec; struct gprs_rlcmac_ul_tbf *tbf; - unsigned len = cs.maxBytesUL(); + unsigned len = cs.sizeUL(); /* These are always data blocks, since EGPRS still uses CS-1 for * control blocks (see 44.060, section 10.3, 1st par.) @@ -1180,6 +1344,8 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn, } } + LOGP(DRLCMACUL, LOGL_DEBUG, " UL data: %s\n", osmo_hexdump(data, len)); + rc = Decoding::rlc_parse_ul_data_header(&rlc_dec, data, cs); if (rc < 0) { LOGP(DRLCMACUL, LOGL_ERROR, @@ -1205,7 +1371,7 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn, return 0; } - return tbf->rcv_data_block_acknowledged(&rlc_dec, data, len, meas); + return tbf->rcv_data_block_acknowledged(&rlc_dec, data, meas); } int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn, @@ -1239,13 +1405,15 @@ int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn, 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( + LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi, enum gprs_rlcmac_tbf_direction dir) { gprs_rlcmac_tbf *tbf; - struct llist_pods *lpods; + LListHead<gprs_rlcmac_tbf> *pos; - llist_pods_for_each_entry(tbf, tbf_list, list, lpods) { + llist_for_each(pos, tbf_list) { + tbf = pos->entry(); if (tbf->tfi() != tfi) continue; if (!tbf->pdch[ts_no]) @@ -1257,14 +1425,12 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi) { - return static_cast<gprs_rlcmac_ul_tbf *>( - tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF)); + return as_ul_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF)); } gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi) { - return static_cast<gprs_rlcmac_dl_tbf *>( - tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF)); + return as_dl_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF)); } /* lookup TBF Entity (by TFI) */ @@ -1300,7 +1466,7 @@ void gprs_rlcmac_pdch::attach_tbf(gprs_rlcmac_tbf *tbf) m_num_tbfs[tbf->direction] += 1; if (tbf->direction == GPRS_RLCMAC_UL_TBF) { - ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf); + ul_tbf = as_ul_tbf(tbf); m_assigned_usf |= 1 << ul_tbf->m_usf[ts_no]; } m_assigned_tfi[tbf->direction] |= 1UL << tbf->tfi(); @@ -1320,7 +1486,7 @@ void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf) m_num_tbfs[tbf->direction] -= 1; if (tbf->direction == GPRS_RLCMAC_UL_TBF) { - ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf); + ul_tbf = as_ul_tbf(tbf); m_assigned_usf &= ~(1 << ul_tbf->m_usf[ts_no]); } m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi()); |