diff options
Diffstat (limited to 'src/gprs_rlcmac.cpp')
-rw-r--r-- | src/gprs_rlcmac.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 2c87317..2ea0a61 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; +} + |