From: Holger Hans Peter Freyther <holger(a)moiji-mobile.com>
* Create a look up routine for the TBF that will allow us to
easily find a TBF by IMSI...
* Separate the code that works on an existing TBF.
---
src/tbf.cpp | 119 +++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 70 insertions(+), 49 deletions(-)
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 816fdb8..d242b52 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -29,66 +29,87 @@ extern "C" {
#include <errno.h>
#include <string.h>
+static struct gprs_rlcmac_tbf *tbf_lookup_dl(const uint32_t tlli, const char *imsi)
+{
+ /* TODO: look up by IMSI first, then tlli, then old_tlli */
+ return tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF);
+}
+
+static int tbf_append_data(struct gprs_rlcmac_tbf *tbf,
+ struct gprs_rlcmac_bts *bts,
+ const uint8_t ms_class,
+ const uint16_t pdu_delay_csec,
+ const uint8_t *data, const uint16_t len)
+{
+ LOGP(DRLCMAC, LOGL_INFO, "TBF: APPEND TFI: %u TLLI: 0x%08x\n", tbf->tfi,
tbf->tlli);
+ if (tbf->state == GPRS_RLCMAC_WAIT_RELEASE) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "TBF in WAIT RELEASE state "
+ "(T3193), so reuse TBF\n");
+ memcpy(tbf->llc_frame, data, len);
+ tbf->llc_length = len;
+ /* reset rlc states */
+ memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl));
+ /* keep to flags */
+ tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+ tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+ if (!tbf->ms_class && ms_class)
+ tbf->ms_class = ms_class;
+ tbf_update(tbf);
+ gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
+ } else {
+ /* the TBF exists, so we must write it in the queue
+ * we prepend lifetime in front of PDU */
+ struct timeval *tv;
+ struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv),
+ "llc_pdu_queue");
+ if (!llc_msg)
+ return -ENOMEM;
+ tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
+
+ uint16_t delay_csec;
+ if (bts->force_llc_lifetime)
+ delay_csec = bts->force_llc_lifetime;
+ else
+ delay_csec = pdu_delay_csec;
+ /* keep timestap at 0 for infinite delay */
+ if (delay_csec != 0xffff) {
+ /* calculate timestamp of timeout */
+ gettimeofday(tv, NULL);
+ tv->tv_usec += (delay_csec % 100) * 10000;
+ tv->tv_sec += delay_csec / 100;
+ if (tv->tv_usec > 999999) {
+ tv->tv_usec -= 1000000;
+ tv->tv_sec++;
+ }
+ }
+ memcpy(msgb_put(llc_msg, len), data, len);
+ msgb_enqueue(&tbf->llc_queue, llc_msg);
+ /* set ms class for updating TBF */
+ if (!tbf->ms_class && ms_class)
+ tbf->ms_class = ms_class;
+ }
+
+ return 0;
+}
+
/**
* TODO: split into unit test-able parts...
*/
int tbf_handle(struct gprs_rlcmac_bts *bts,
const uint32_t tlli, const char *imsi,
- const uint8_t ms_class, const uint16_t pdu_delay_csec,
+ const uint8_t ms_class, const uint16_t delay_csec,
const uint8_t *data, const uint16_t len)
{
struct gprs_rlcmac_tbf *tbf;
int8_t tfi; /* must be signed */
/* check for existing TBF */
- if ((tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
- LOGP(DRLCMAC, LOGL_INFO, "TBF: APPEND TFI: %u TLLI: 0x%08x\n", tbf->tfi,
tbf->tlli);
- if (tbf->state == GPRS_RLCMAC_WAIT_RELEASE) {
- LOGP(DRLCMAC, LOGL_DEBUG, "TBF in WAIT RELEASE state "
- "(T3193), so reuse TBF\n");
- memcpy(tbf->llc_frame, data, len);
- tbf->llc_length = len;
- memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset
- rlc states */
- tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep
- to flags */
- tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
- if (!tbf->ms_class && ms_class)
- tbf->ms_class = ms_class;
- tbf_update(tbf);
- gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
- } else {
- /* the TBF exists, so we must write it in the queue
- * we prepend lifetime in front of PDU */
- struct timeval *tv;
- struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv),
- "llc_pdu_queue");
- if (!llc_msg)
- return -ENOMEM;
- tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
-
- uint16_t delay_csec;
- if (bts->force_llc_lifetime)
- delay_csec = bts->force_llc_lifetime;
- else
- delay_csec = pdu_delay_csec;
- /* keep timestap at 0 for infinite delay */
- if (delay_csec != 0xffff) {
- /* calculate timestamp of timeout */
- gettimeofday(tv, NULL);
- tv->tv_usec += (delay_csec % 100) * 10000;
- tv->tv_sec += delay_csec / 100;
- if (tv->tv_usec > 999999) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
- }
- memcpy(msgb_put(llc_msg, len), data, len);
- msgb_enqueue(&tbf->llc_queue, llc_msg);
- /* set ms class for updating TBF */
- if (!tbf->ms_class && ms_class)
- tbf->ms_class = ms_class;
- }
+ tbf = tbf_lookup_dl(tlli, imsi);
+ if (tbf) {
+ int rc = tbf_append_data(tbf, bts, ms_class,
+ delay_csec, data, len);
+ if (rc < 0)
+ return rc;
} else {
uint8_t trx, ta, ss;
int8_t use_trx;
--
1.8.4.rc3