diff options
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 15 | ||||
-rw-r--r-- | src/gprs_rlcmac.cpp | 104 | ||||
-rw-r--r-- | src/gprs_rlcmac.h | 8 | ||||
-rw-r--r-- | src/gprs_rlcmac_data.cpp | 44 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 5 | ||||
-rw-r--r-- | src/pcu_l1_if.cpp | 18 | ||||
-rw-r--r-- | src/pcu_main.cpp | 2 |
7 files changed, 185 insertions, 11 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index 5dbfb2c1..54753b85 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -196,6 +196,7 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) uint8_t trx, ta, ss; int8_t use_trx; struct gprs_rlcmac_tbf *old_tbf; + int rc; /* check for uplink data, so we copy our informations */ tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF); @@ -207,7 +208,19 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) old_tbf = tbf; } else { use_trx = -1; - ta = 0; /* FIXME: initial TA */ + /* we already have an uplink TBF, so we use that TA */ + if (tbf) + ta = tbf->ta; + else { + /* recall TA */ + rc = recall_timing_advance(tlli); + if (rc < 0) { + LOGP(DRLCMAC, LOGL_NOTICE, "TA unknown" + ", assuming 0\n"); + ta = 0; + } else + ta = rc; + } ss = 1; /* PCH assignment only allows one timeslot */ old_tbf = NULL; } diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 2c873172..2ea0a614 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -1819,3 +1819,107 @@ int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, return 0; } + + +/* + * timing advance memory + */ + +/* enable to debug timing advance memory */ +//#define DEBUG_TA + +static LLIST_HEAD(gprs_rlcmac_ta_list); +static int gprs_rlcmac_ta_num = 0; + +struct gprs_rlcmac_ta { + struct llist_head list; + uint32_t tlli; + uint8_t ta; +}; + +/* remember timing advance of a given TLLI */ +int remember_timing_advance(uint32_t tlli, uint8_t ta) +{ + struct gprs_rlcmac_ta *ta_entry; + + /* check for existing entry */ + llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) { + if (ta_entry->tlli == tlli) { +#ifdef DEBUG_TA + fprintf(stderr, "update %08x %d\n", tlli, ta); +#endif + ta_entry->ta = ta; + /* relink to end of list */ + llist_del(&ta_entry->list); + llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list); + return 0; + } + } + +#ifdef DEBUG_TA + fprintf(stderr, "remember %08x %d\n", tlli, ta); +#endif + /* if list is full, remove oldest entry */ + if (gprs_rlcmac_ta_num == 30) { + ta_entry = llist_entry(gprs_rlcmac_ta_list.next, + struct gprs_rlcmac_ta, list); + llist_del(&ta_entry->list); + talloc_free(ta_entry); + gprs_rlcmac_ta_num--; + } + + /* create new TA entry */ + ta_entry = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ta); + if (!ta_entry) + return -ENOMEM; + + ta_entry->tlli = tlli; + ta_entry->ta = ta; + llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list); + gprs_rlcmac_ta_num++; + + return 0; +} + +int recall_timing_advance(uint32_t tlli) +{ + struct gprs_rlcmac_ta *ta_entry; + uint8_t ta; + + llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) { + if (ta_entry->tlli == tlli) { + ta = ta_entry->ta; +#ifdef DEBUG_TA + fprintf(stderr, "recall %08x %d\n", tlli, ta); +#endif + return ta; + } + } +#ifdef DEBUG_TA + fprintf(stderr, "no entry for %08x\n", tlli); +#endif + + return -EINVAL; +} + +int flush_timing_advance(void) +{ + struct gprs_rlcmac_ta *ta_entry; + int count = 0; + + while (!llist_empty(&gprs_rlcmac_ta_list)) { + ta_entry = llist_entry(gprs_rlcmac_ta_list.next, + struct gprs_rlcmac_ta, list); +#ifdef DEBUG_TA + fprintf(stderr, "flush entry %08x %d\n", ta_entry->tlli, + ta_entry->ta); +#endif + llist_del(&ta_entry->list); + talloc_free(ta_entry); + count++; + } + gprs_rlcmac_ta_num = 0; + + return count; +} + diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index 5badb120..c5af6029 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -374,6 +374,8 @@ void tbf_timer_cb(void *_tbf); int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf); +int gprs_rlcmac_sba_timeout(struct gprs_rlcmac_sba *sba); + int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta); int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, @@ -421,6 +423,12 @@ struct gprs_rlcmac_paging *gprs_rlcmac_dequeue_paging( struct msgb *gprs_rlcmac_send_packet_paging_request( struct gprs_rlcmac_pdch *pdch); +int remember_timing_advance(uint32_t tlli, uint8_t ta); + +int recall_timing_advance(uint32_t tlli); + +int flush_timing_advance(void); + extern "C" { #endif int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf, diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 1109451e..4f2b649a 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -206,6 +206,15 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) return 0; } +int gprs_rlcmac_sba_timeout(struct gprs_rlcmac_sba *sba) +{ + LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for SBA\n"); + llist_del(&sba->list); + talloc_free(sba); + + return 0; +} + static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap) { int i; @@ -263,6 +272,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, int8_t tfi = 0; /* must be signed */ uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; + struct gprs_rlcmac_sba *sba; int rc; RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t); @@ -420,6 +430,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, if (!tbf) { uint8_t ms_class = 0; struct gprs_rlcmac_tbf *dl_tbf; + uint8_t ta; if ((dl_tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) { LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from " @@ -431,12 +442,28 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF " "in packet ressource request of single " "block, so we provide one:\n"); + sba = sba_find(trx, ts, fn); + if (!sba) { + LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF " + "in packet ressource request of single " + "block, but there is no resource request " + "scheduled!\n"); + rc = recall_timing_advance(tlli); + if (rc >= 0) + ta = rc; + else + ta = 0; + } else { + ta = sba->ta; + remember_timing_advance(tlli, ta); + llist_del(&sba->list); + talloc_free(sba); + } if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability) ms_class = get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability); if (!ms_class) LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n"); - tbf = alloc_ul_tbf(trx, ms_class, tlli, 0, NULL); -#warning FIXME TA!!! + tbf = alloc_ul_tbf(trx, ms_class, tlli, ta, NULL); if (!tbf) break; /* set control ts to current MS's TS, until assignment complete */ @@ -469,6 +496,17 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x FIXME: Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli); break; case MT_PACKET_MEASUREMENT_REPORT: + sba = sba_find(trx, ts, fn); + if (!sba) { + LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement " + "in packet ressource request of single " + "block, but there is no resource request " + "scheduled!\n"); + } else { + remember_timing_advance(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta); + llist_del(&sba->list); + talloc_free(sba); + } gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report); break; default: @@ -888,6 +926,8 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, } /* mark TLLI valid now */ tbf->tlli_valid = 1; + /* store current timing advance */ + remember_timing_advance(tbf->tlli, tbf->ta); /* already have TLLI, but we stille get another one */ } else if (rh->ti) { uint32_t tlli; diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index f588c47d..9b31fbc3 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -78,11 +78,8 @@ uint32_t sched_sba(uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr) sba_fn ++; sba_fn = sba_fn % 2715648; sba = sba_find(trx, ts, sba_fn); - if (sba) { - llist_del(&sba->list); - talloc_free(sba); + if (sba) return sba_fn; - } return 0xffffffff; } diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index d7f5ec44..923070f1 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -516,6 +516,7 @@ bssgp_failed: static int pcu_rx_time_ind(struct gsm_pcu_if_time_ind *time_ind) { struct gprs_rlcmac_tbf *tbf; + struct gprs_rlcmac_sba *sba, *sba2; uint32_t elapsed; uint8_t fn13 = time_ind->fn % 13; @@ -531,18 +532,27 @@ static int pcu_rx_time_ind(struct gsm_pcu_if_time_ind *time_ind) /* check for poll timeout */ llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) { if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) { - elapsed = (frame_number - tbf->poll_fn) % 2715648; - if (elapsed >= 20 && elapsed < 200) + elapsed = (frame_number + 2715648 - tbf->poll_fn) + % 2715648; + if (elapsed >= 20 && elapsed < 2715400) gprs_rlcmac_poll_timeout(tbf); } } llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) { if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) { - elapsed = (frame_number - tbf->poll_fn) % 2715648; - if (elapsed >= 20 && elapsed < 200) + elapsed = (frame_number + 2715648 - tbf->poll_fn) + % 2715648; + if (elapsed >= 20 && elapsed < 2715400) gprs_rlcmac_poll_timeout(tbf); } } + llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) { + elapsed = (frame_number + 2715648 - sba->fn) % 2715648; + if (elapsed >= 20 && elapsed < 2715400) { + /* sba will be freed here */ + gprs_rlcmac_sba_timeout(sba); + } + } return 0; } diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp index 4f23dd76..041831f6 100644 --- a/src/pcu_main.cpp +++ b/src/pcu_main.cpp @@ -248,6 +248,8 @@ int main(int argc, char *argv[]) pcu_l1if_close(); + flush_timing_advance(); + talloc_free(gprs_rlcmac_bts); talloc_report_full(tall_pcu_ctx, stderr); |