From 61a33f7c7a10100f000a371da0fc819fdfe95a7e Mon Sep 17 00:00:00 2001 From: Ivan Kluchnikov Date: Thu, 12 Apr 2012 15:22:06 +0400 Subject: [PATCH] Added support of osmo_timers and osmo_gsm_timers for TBF. --- gprs_rlcmac.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++---- gprs_rlcmac.h | 10 +++++++ pcu_main.cpp | 13 +++++++++- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/gprs_rlcmac.cpp b/gprs_rlcmac.cpp index 72a1e296..eb636815 100644 --- a/gprs_rlcmac.cpp +++ b/gprs_rlcmac.cpp @@ -22,7 +22,6 @@ #include #include - LLIST_HEAD(gprs_rlcmac_tbfs); void *rlcmac_tall_ctx; @@ -89,6 +88,69 @@ static void tbf_free(struct gprs_rlcmac_tbf *tbf) talloc_free(tbf); } + +static void tbf_timer_cb(void *_tbf) +{ + struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf; + + tbf->num_T_exp++; + + switch (tbf->T) { + case 1111: + // TODO: We should add timers for TBF. + break; + default: + COUT("Timer expired in unknown mode" << tbf->T); + } +} + +static void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T, + unsigned int seconds) +{ + if (osmo_timer_pending(&tbf->timer)) + COUT("Starting TBF timer %u while old timer %u pending" << T << tbf->T); + tbf->T = T; + tbf->num_T_exp = 0; + + /* FIXME: we should do this only once ? */ + tbf->timer.data = tbf; + tbf->timer.cb = &tbf_timer_cb; + + osmo_timer_schedule(&tbf->timer, seconds, 0); +} + + +static void tbf_gsm_timer_cb(void *_tbf) +{ + struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf; + + tbf->num_fT_exp++; + + switch (tbf->fT) { + case 0: + // This is timer for delay RLC/MAC data sending after Downlink Immediate Assignment on CCCH. + gprs_rlcmac_segment_llc_pdu(tbf); + break; + default: + COUT("Timer expired in unknown mode" << tbf->fT); + } +} + +static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT, + int frames) +{ + if (osmo_gsm_timer_pending(&tbf->gsm_timer)) + COUT("Starting TBF timer %u while old timer %u pending" << fT << tbf->fT); + tbf->fT = fT; + tbf->num_fT_exp = 0; + + /* FIXME: we should do this only once ? */ + tbf->gsm_timer.data = tbf; + tbf->gsm_timer.cb = &tbf_gsm_timer_cb; + + osmo_gsm_timer_schedule(&tbf->gsm_timer, frames); +} + void write_packet_downlink_assignment(BitVector * dest, uint8_t tfi, uint32_t tlli) { // TODO We should use our implementation of encode RLC/MAC Control messages. @@ -526,13 +588,10 @@ void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf) void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf) { - COUT("SEND IA Rest Octets Downlink Assignment>>>>>>>>>>>>>>>>>>"); BitVector ia_rest_octets_downlink_assignment(23*8); ia_rest_octets_downlink_assignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); write_ia_rest_octets_downlink_assignment(&ia_rest_octets_downlink_assignment, tbf->tfi, tbf->tlli); pcu_l1if_tx(&ia_rest_octets_downlink_assignment); - - usleep(500000); - gprs_rlcmac_segment_llc_pdu(tbf); + tbf_gsm_timer_start(tbf, 0, 120); } diff --git a/gprs_rlcmac.h b/gprs_rlcmac.h index eadafd14..38e29630 100644 --- a/gprs_rlcmac.h +++ b/gprs_rlcmac.h @@ -22,9 +22,11 @@ #include #include +#include extern "C" { #include +#include } enum gprs_rlcmac_tbf_state { @@ -47,6 +49,14 @@ struct gprs_rlcmac_tbf { uint8_t rlc_data[60]; uint16_t data_index; uint8_t bsn; + + struct osmo_timer_list timer; + unsigned int T; /* Txxxx number */ + unsigned int num_T_exp; /* number of consecutive T expirations */ + + struct osmo_gsm_timer_list gsm_timer; + unsigned int fT; /* fTxxxx number */ + unsigned int num_fT_exp; /* number of consecutive fT expirations */ }; extern struct llist_head gprs_rlcmac_tbfs; diff --git a/pcu_main.cpp b/pcu_main.cpp index d4b3938b..2417d08b 100644 --- a/pcu_main.cpp +++ b/pcu_main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include // TODO: We should move this parameters to config file. #define SGSN_IP "127.0.0.1" @@ -85,7 +86,7 @@ static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg) int rc; struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data; - DEBUGP(DGPRS, "UDP: Writing %u bytes for MQ_L1_WRITE queue\n", msgb_l1len(msg)); + //DEBUGP(DGPRS, "UDP: Writing %u bytes for MQ_L1_WRITE queue\n", msgb_l1len(msg)); rc = sendto(ofd->fd, msg->l1h, msgb_l1len(msg), 0, (const struct sockaddr *)&l1fh->remote_sa, l1fh->remote_sa_len); @@ -115,6 +116,12 @@ int pcu_l1if_open() l1fh->fl1h = fl1h; fl1h->priv = l1fh; + struct osmo_wqueue * queue = &((l1fh->fl1h)->write_q); + osmo_wqueue_init(queue, 10); + queue->bfd.when |= BSC_FD_READ; + queue->bfd.data = l1fh; + queue->bfd.priv_nr = 0; + /* Open UDP */ struct osmo_wqueue *wq = &l1fh->udp_wq; @@ -170,6 +177,10 @@ int main(int argc, char *argv[]) unsigned i = 0; while (1) { + osmo_gsm_timers_check(); + osmo_gsm_timers_prepare(); + osmo_gsm_timers_update(); + osmo_select_main(0); if (i == 7) {