aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_bssgp_pcu.cpp
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-08-24 18:31:27 +0200
committerIvan Kluchnikov <kluchnikovi@gmail.com>2013-10-18 15:15:49 +0400
commit17c31ce173699377da5d44b3bdb69583c400d5b9 (patch)
tree7e9a6009949adef726bd80efc11051de90ca86d9 /src/gprs_bssgp_pcu.cpp
parentdcc9c39529556ca20cb8bd98758ea8caa023f259 (diff)
tbf: Begin to add some structure to the tbf code
The TBF should use the IMSI to identify a block flow but all handling is spread across the entire code. Start to clean this up by moving relevant code into the tbf file. Afterwards one can clean up and add more internal structure.
Diffstat (limited to 'src/gprs_bssgp_pcu.cpp')
-rw-r--r--src/gprs_bssgp_pcu.cpp121
1 files changed, 3 insertions, 118 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 4833af8a..3432bca8 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -21,6 +21,7 @@
#include <gprs_rlcmac.h>
#include <gprs_bssgp_pcu.h>
#include <pcu_l1_if.h>
+#include <tbf.h>
static struct gprs_bssgp_pcu the_pcu = { 0, };
@@ -103,12 +104,9 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
{
struct bssgp_ud_hdr *budh;
- int8_t tfi; /* must be signed */
-
uint32_t tlli;
uint8_t *data;
uint16_t len;
- struct gprs_rlcmac_tbf *tbf;
char imsi[16] = "000";
budh = (struct bssgp_ud_hdr *)msgb_bssgph(msg);
@@ -123,7 +121,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
data = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
- if (len > sizeof(tbf->llc_frame))
+ if (len > sizeof(gprs_rlcmac_tbf::llc_frame))
{
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP TLLI=0x%08x Rx UL-UD IE_LLC_PDU too large\n", tlli);
return bssgp_tx_status(BSSGP_CAUSE_COND_IE_ERR, NULL, msg);
@@ -154,120 +152,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len);
- /* 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));
- if (the_pcu.bts->force_llc_lifetime)
- delay_csec = the_pcu.bts->force_llc_lifetime;
- /* 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;
- }
- } else {
- 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);
- if (tbf && tbf->dir.ul.contention_resolution_done
- && !tbf->dir.ul.final_ack_sent) {
- use_trx = tbf->trx;
- ta = tbf->ta;
- ss = 0;
- old_tbf = tbf;
- } else {
- use_trx = -1;
- /* 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;
- }
-
- // Create new TBF (any TRX)
- tfi = tfi_find_free(the_pcu.bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx);
- if (tfi < 0) {
- LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
- /* FIXME: send reject */
- return -EBUSY;
- }
- /* set number of downlink slots according to multislot class */
- tbf = tbf_alloc(the_pcu.bts, tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class,
- ss);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
- /* FIXME: send reject */
- return -EBUSY;
- }
- tbf->tlli = tlli;
- tbf->tlli_valid = 1;
- tbf->ta = ta;
-
- LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] START TFI: %d TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
-
- /* new TBF, so put first frame */
- memcpy(tbf->llc_frame, data, len);
- tbf->llc_length = len;
-
- /* trigger downlink assignment and set state to ASSIGN.
- * we don't use old_downlink, so the possible uplink is used
- * to trigger downlink assignment. if there is no uplink,
- * AGCH is used. */
- gprs_rlcmac_trigger_downlink_assignment(tbf, old_tbf, imsi);
- }
-
- /* store IMSI for debugging purpose */
- strncpy(tbf->meas.imsi, imsi, sizeof(tbf->meas.imsi) - 1);
-
- return 0;
+ return tbf_handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len);
}
int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp)