diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/bts.cpp | 6 | ||||
-rw-r--r-- | src/bts.h | 5 | ||||
-rw-r--r-- | src/gprs_ms.cpp | 1 | ||||
-rw-r--r-- | src/gprs_ms.h | 2 | ||||
-rw-r--r-- | src/gprs_rlcmac.cpp | 21 | ||||
-rw-r--r-- | src/gprs_rlcmac.h | 3 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 89 | ||||
-rw-r--r-- | src/pcu_l1_if.cpp | 39 |
9 files changed, 140 insertions, 29 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 233e24de..7148267b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,8 @@ libgprs_la_SOURCES = \ gprs_codel.c \ coding_scheme.c \ gprs_coding_scheme.cpp \ - egprs_rlc_compression.cpp + egprs_rlc_compression.cpp \ + gprs_rlcmac_sched.cpp bin_PROGRAMS = \ osmo-pcu diff --git a/src/bts.cpp b/src/bts.cpp index 8b32e2ed..1b2ab2fb 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -231,6 +231,7 @@ BTS::BTS() { memset(&m_bts, 0, sizeof(m_bts)); m_bts.bts = this; + m_bts.app_info = NULL; m_bts.dl_tbf_preemptive_retransmission = true; m_bts.T_defs_bts = T_defs_bts; m_bts.T_defs_pcu = T_defs_pcu; @@ -279,6 +280,11 @@ void BTS::cleanup() osmo_stat_item_group_free(m_statg); m_statg = NULL; } + + if (m_bts.app_info) { + msgb_free(m_bts.app_info); + m_bts.app_info = NULL; + } } BTS::~BTS() @@ -164,6 +164,11 @@ struct gprs_rlcmac_bts { /* Are we talking Gb with IP-SNS (true) or classic Gb? */ bool gb_dialect_sns; + + /* Packet Application Information (3GPP TS 44.060 11.2.47, usually ETWS primary message). We don't need to store + * more than one message, because they get sent so rarely. */ + struct msgb *app_info; + uint32_t app_info_pending; /* Count of MS with active TBF, to which we did not send app_info yet */ }; #ifdef __cplusplus diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index 19f2ecb2..75f75e17 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -135,6 +135,7 @@ GprsMs::GprsMs(BTS *bts, uint32_t tlli) : gprs_codel_set_interval(m_codel_state, codel_interval); } m_last_cs_not_low = now_msec(); + app_info_pending = false; } GprsMs::~GprsMs() diff --git a/src/gprs_ms.h b/src/gprs_ms.h index ad8ca1da..781dd59f 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -136,6 +136,8 @@ public: /* internal use */ static void timeout(void *priv_); + bool app_info_pending; + protected: void update_status(); GprsMs *ref(); diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 5a223c13..4d93f8f0 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -41,4 +41,25 @@ int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, return 0; } +/* Encode Application Information Request to Packet Application Information (3GPP TS 44.060 11.2.47) */ +struct msgb *gprs_rlcmac_app_info_msg(const struct gsm_pcu_if_app_info_req *req) { + struct msgb *msg; + uint16_t msgb_len = req->len + 1; + struct bitvec bv = {0, msgb_len, NULL}; + const enum bit_value page_mode[] = {ZERO, ZERO}; /* Normal Paging (3GPP TS 44.060 12.20) */ + if (!req->len) { + LOGP(DRLCMAC, LOGL_ERROR, "Application Information Request with zero length received!\n"); + return NULL; + } + + msg = msgb_alloc(msgb_len, "app_info_msg"); + if (!msg) + return NULL; + + bv.data = msgb_put(msg, msgb_len); + bitvec_set_bits(&bv, page_mode, 2); + bitvec_set_uint(&bv, req->application_type, 4); + bitvec_set_bytes(&bv, req->data, req->len); + return msg; +} diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index 7a3a7af5..16cb05f2 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -31,6 +31,7 @@ extern "C" { #include <osmocom/core/linuxlist.h> #include <osmocom/core/timer.h> #include <osmocom/core/bitvec.h> +#include <osmocom/pcu/pcuif_proto.h> } #endif @@ -94,6 +95,8 @@ int gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf); int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, const char *imsi); +struct msgb *gprs_rlcmac_app_info_msg(const struct gsm_pcu_if_app_info_req *req); + int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr); diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 57756e3b..7356523f 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -123,6 +123,34 @@ static uint8_t sched_select_uplink(uint8_t trx, uint8_t ts, uint32_t fn, return usf; } +struct msgb *sched_app_info(struct gprs_rlcmac_tbf *tbf) { + struct gprs_rlcmac_bts *bts_data; + struct msgb *msg = NULL; + + if (!tbf || !tbf->ms()->app_info_pending) + return NULL; + + bts_data = BTS::main_bts()->bts_data(); + + if (bts_data->app_info) { + LOGP(DRLCMACSCHED, LOGL_DEBUG, "Sending Packet Application Information message\n"); + msg = msgb_copy(bts_data->app_info, "app_info_msg_sched"); + } else + LOGP(DRLCMACSCHED, LOGL_ERROR, "MS has app_info_pending flag set, but no Packet Application Information" + " message stored in BTS!\n"); + + tbf->ms()->app_info_pending = false; + bts_data->app_info_pending--; + + if (!bts_data->app_info_pending) { + LOGP(DRLCMACSCHED, LOGL_DEBUG, "Packet Application Information successfully sent to all MS with active" + " TBF\n"); + msgb_free(bts_data->app_info); + bts_data->app_info = NULL; + } + return msg; +} + static struct msgb *sched_select_ctrl_msg( uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr, struct gprs_rlcmac_pdch *pdch, @@ -134,37 +162,42 @@ static struct msgb *sched_select_ctrl_msg( struct gprs_rlcmac_tbf *tbf = NULL; struct gprs_rlcmac_tbf *next_list[3] = { ul_ass_tbf, dl_ass_tbf, ul_ack_tbf }; - for (size_t i = 0; i < ARRAY_SIZE(next_list); ++i) { - tbf = next_list[(pdch->next_ctrl_prio + i) % 3]; - if (!tbf) - continue; + /* Send Packet Application Information first (ETWS primary notifications) */ + msg = sched_app_info(dl_ass_tbf); - /* - * Assignments for the same direction have lower precedence, - * because they may kill the TBF when the CONTROL ACK is - * received, thus preventing the others from being processed. - */ - if (tbf == ul_ass_tbf && tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) - msg = ul_ass_tbf->create_packet_access_reject(); - else if (tbf == ul_ass_tbf && tbf->direction == - GPRS_RLCMAC_DL_TBF) - if (tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) + if (!msg) { + for (size_t i = 0; i < ARRAY_SIZE(next_list); ++i) { + tbf = next_list[(pdch->next_ctrl_prio + i) % 3]; + if (!tbf) + continue; + + /* + * Assignments for the same direction have lower precedence, + * because they may kill the TBF when the CONTROL ACK is + * received, thus preventing the others from being processed. + */ + if (tbf == ul_ass_tbf && tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) msg = ul_ass_tbf->create_packet_access_reject(); - else - msg = ul_ass_tbf->create_ul_ass(fn, ts); - else if (tbf == dl_ass_tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) - msg = dl_ass_tbf->create_dl_ass(fn, ts); - else if (tbf == ul_ack_tbf) - msg = ul_ack_tbf->create_ul_ack(fn, ts); - - if (!msg) { - tbf = NULL; - continue; + else if (tbf == ul_ass_tbf && tbf->direction == + GPRS_RLCMAC_DL_TBF) + if (tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) + msg = ul_ass_tbf->create_packet_access_reject(); + else + msg = ul_ass_tbf->create_ul_ass(fn, ts); + else if (tbf == dl_ass_tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) + msg = dl_ass_tbf->create_dl_ass(fn, ts); + else if (tbf == ul_ack_tbf) + msg = ul_ack_tbf->create_ul_ack(fn, ts); + + if (!msg) { + tbf = NULL; + continue; + } + + pdch->next_ctrl_prio += 1; + pdch->next_ctrl_prio %= 3; + break; } - - pdch->next_ctrl_prio += 1; - pdch->next_ctrl_prio %= 3; - break; } if (!msg) { diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 6ffebcf6..8901ce6f 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -620,6 +620,42 @@ static int pcu_rx_susp_req(struct gsm_pcu_if_susp_req *susp_req) return bssgp_tx_suspend(bctx->nsei, susp_req->tlli, &ra_id); } +static int pcu_rx_app_info_req(struct gsm_pcu_if_app_info_req *app_info_req) +{ + LListHead<GprsMs> *ms_iter; + BTS *bts = BTS::main_bts(); + struct gprs_rlcmac_bts *bts_data = bts->bts_data(); + + LOGP(DL1IF, LOGL_DEBUG, "Application Information Request received: type=0x%08x len=%i\n", + app_info_req->application_type, app_info_req->len); + + bts_data->app_info_pending = 0; + llist_for_each(ms_iter, &bts->ms_store().ms_list()) { + GprsMs *ms = ms_iter->entry(); + if (!ms->dl_tbf()) + continue; + bts_data->app_info_pending++; + ms->app_info_pending = true; + } + + if (!bts_data->app_info_pending) { + LOGP(DL1IF, LOGL_NOTICE, "Packet Application Information will not be sent, no subscribers with active" + " TBF\n"); + return -1; + } + + if (bts_data->app_info) { + LOGP(DL1IF, LOGL_NOTICE, "Previous Packet Application Information was not sent to all subscribers," + " overwriting with new one\n"); + msgb_free(bts_data->app_info); + } + + LOGP(DL1IF, LOGL_INFO, "Sending Packet Application Information to %i subscribers with active TBF\n", + bts_data->app_info_pending); + bts_data->app_info = gprs_rlcmac_app_info_msg(app_info_req); + return 0; +} + int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim) { int rc = 0; @@ -649,6 +685,9 @@ int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim) case PCU_IF_MSG_SUSP_REQ: rc = pcu_rx_susp_req(&pcu_prim->u.susp_req); break; + case PCU_IF_MSG_APP_INFO_REQ: + rc = pcu_rx_app_info_req(&pcu_prim->u.app_info_req); + break; default: LOGP(DL1IF, LOGL_ERROR, "Received unknown PCU msg type %d\n", msg_type); |