pdch: Move paging dequeue into the PDCH object

Rely on packet_paging_request returning NULL in case the queue
is empty. We should move the write_packet_paging_request into
a separate file/object as well.
This commit is contained in:
Holger Hans Peter Freyther 2013-10-19 18:15:44 +02:00
parent 17b0d83a1f
commit 24e98d039d
5 changed files with 104 additions and 103 deletions

View File

@ -23,13 +23,19 @@
#include <tbf.h>
#include <gprs_rlcmac.h>
#include <gprs_debug.h>
extern "C" {
#include <osmocom/core/talloc.h>
#include <osmocom/core/msgb.h>
}
#include <arpa/inet.h>
#include <string.h>
extern void *tall_pcu_ctx;
static BTS s_bts;
BTS* BTS::main_bts()
@ -87,7 +93,7 @@ void gprs_rlcmac_pdch::free_resources(uint8_t trx, uint8_t ts)
gprs_rlcmac_tbf::free_all(this);
/* flush all pending paging messages */
while ((pag = gprs_rlcmac_dequeue_paging(this)))
while ((pag = dequeue_paging()))
talloc_free(pag);
llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) {
@ -97,3 +103,95 @@ void gprs_rlcmac_pdch::free_resources(uint8_t trx, uint8_t ts)
}
}
}
struct gprs_rlcmac_paging *gprs_rlcmac_pdch::dequeue_paging()
{
struct gprs_rlcmac_paging *pag;
if (llist_empty(&paging_list))
return NULL;
pag = llist_entry(paging_list.next, struct gprs_rlcmac_paging, list);
llist_del(&pag->list);
return pag;
}
struct msgb *gprs_rlcmac_pdch::packet_paging_request()
{
struct gprs_rlcmac_paging *pag;
struct msgb *msg;
unsigned wp = 0, len;
/* no paging, no message */
pag = dequeue_paging();
if (!pag)
return NULL;
LOGP(DRLCMAC, LOGL_DEBUG, "Scheduling paging\n");
/* alloc message */
msg = msgb_alloc(23, "pag ctrl block");
if (!msg) {
talloc_free(pag);
return NULL;
}
bitvec *pag_vec = bitvec_alloc(23);
if (!pag_vec) {
msgb_free(msg);
talloc_free(pag);
return NULL;
}
wp = write_packet_paging_request(pag_vec);
/* loop until message is full */
while (pag) {
/* try to add paging */
if ((pag->identity_lv[1] & 0x07) == 4) {
/* TMSI */
LOGP(DRLCMAC, LOGL_DEBUG, "- TMSI=0x%08x\n",
ntohl(*((uint32_t *)(pag->identity_lv + 1))));
len = 1 + 1 + 1 + 32 + 2 + 1;
if (pag->identity_lv[0] != 5) {
LOGP(DRLCMAC, LOGL_ERROR, "TMSI paging with "
"MI != 5 octets!\n");
goto continue_next;
}
} else {
/* MI */
LOGP(DRLCMAC, LOGL_DEBUG, "- MI=%s\n",
osmo_hexdump(pag->identity_lv + 1,
pag->identity_lv[0]));
len = 1 + 1 + 1 + 4 + (pag->identity_lv[0]<<3) + 2 + 1;
if (pag->identity_lv[0] > 8) {
LOGP(DRLCMAC, LOGL_ERROR, "Paging with "
"MI > 8 octets!\n");
goto continue_next;
}
}
if (wp + len > 184) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Does not fit, so schedule "
"next time\n");
/* put back paging record, because does not fit */
llist_add_tail(&pag->list, &paging_list);
break;
}
write_repeated_page_info(pag_vec, wp, pag->identity_lv[0],
pag->identity_lv + 1, pag->chan_needed);
continue_next:
talloc_free(pag);
pag = dequeue_paging();
}
bitvec_pack(pag_vec, msgb_put(msg, 23));
RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Paging Request +++++++++++++++++++++++++\n");
decode_gsm_rlcmac_downlink(pag_vec, mac_control_block);
LOGPC(DCSN1, LOGL_NOTICE, "\n");
LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Paging Request -------------------------\n");
bitvec_free(pag_vec);
talloc_free(mac_control_block);
return msg;
}

View File

@ -40,6 +40,10 @@ struct BTS;
*/
struct gprs_rlcmac_pdch {
#ifdef __cplusplus
struct gprs_rlcmac_paging *dequeue_paging();
struct msgb *packet_paging_request();
/* TODO: the PDCH should know the trx/ts it belongs to */
void free_resources(uint8_t trx, uint8_t ts);

View File

@ -358,100 +358,6 @@ int gprs_rlcmac_add_paging(struct gprs_rlcmac_bts *bts,
return 0;
}
struct gprs_rlcmac_paging *gprs_rlcmac_dequeue_paging(
struct gprs_rlcmac_pdch *pdch)
{
struct gprs_rlcmac_paging *pag;
if (llist_empty(&pdch->paging_list))
return NULL;
pag = llist_entry(pdch->paging_list.next,
struct gprs_rlcmac_paging, list);
llist_del(&pag->list);
return pag;
}
struct msgb *gprs_rlcmac_send_packet_paging_request(
struct gprs_rlcmac_pdch *pdch)
{
struct gprs_rlcmac_paging *pag;
struct msgb *msg;
unsigned wp = 0, len;
/* no paging, no message */
pag = gprs_rlcmac_dequeue_paging(pdch);
if (!pag)
return NULL;
LOGP(DRLCMAC, LOGL_DEBUG, "Scheduling paging\n");
/* alloc message */
msg = msgb_alloc(23, "pag ctrl block");
if (!msg) {
talloc_free(pag);
return NULL;
}
bitvec *pag_vec = bitvec_alloc(23);
if (!pag_vec) {
msgb_free(msg);
talloc_free(pag);
return NULL;
}
wp = write_packet_paging_request(pag_vec);
/* loop until message is full */
while (pag) {
/* try to add paging */
if ((pag->identity_lv[1] & 0x07) == 4) {
/* TMSI */
LOGP(DRLCMAC, LOGL_DEBUG, "- TMSI=0x%08x\n",
ntohl(*((uint32_t *)(pag->identity_lv + 1))));
len = 1 + 1 + 1 + 32 + 2 + 1;
if (pag->identity_lv[0] != 5) {
LOGP(DRLCMAC, LOGL_ERROR, "TMSI paging with "
"MI != 5 octets!\n");
goto continue_next;
}
} else {
/* MI */
LOGP(DRLCMAC, LOGL_DEBUG, "- MI=%s\n",
osmo_hexdump(pag->identity_lv + 1,
pag->identity_lv[0]));
len = 1 + 1 + 1 + 4 + (pag->identity_lv[0]<<3) + 2 + 1;
if (pag->identity_lv[0] > 8) {
LOGP(DRLCMAC, LOGL_ERROR, "Paging with "
"MI > 8 octets!\n");
goto continue_next;
}
}
if (wp + len > 184) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Does not fit, so schedule "
"next time\n");
/* put back paging record, because does not fit */
llist_add_tail(&pag->list, &pdch->paging_list);
break;
}
write_repeated_page_info(pag_vec, wp, pag->identity_lv[0],
pag->identity_lv + 1, pag->chan_needed);
continue_next:
talloc_free(pag);
pag = gprs_rlcmac_dequeue_paging(pdch);
}
bitvec_pack(pag_vec, msgb_put(msg, 23));
RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Paging Request +++++++++++++++++++++++++\n");
decode_gsm_rlcmac_downlink(pag_vec, mac_control_block);
LOGPC(DCSN1, LOGL_NOTICE, "\n");
LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Paging Request -------------------------\n");
bitvec_free(pag_vec);
talloc_free(mac_control_block);
return msg;
}
// GSM 04.08 9.1.18 Immediate assignment
int write_immediate_assignment(
struct gprs_rlcmac_bts *bts,

View File

@ -192,12 +192,6 @@ int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn);
int gprs_rlcmac_add_paging(struct gprs_rlcmac_bts *bts, uint8_t chan_needed, uint8_t *identity_lv);
struct gprs_rlcmac_paging *gprs_rlcmac_dequeue_paging(
struct gprs_rlcmac_pdch *pdch);
struct msgb *gprs_rlcmac_send_packet_paging_request(
struct gprs_rlcmac_pdch *pdch);
int remember_timing_advance(uint32_t tlli, uint8_t ta);
int recall_timing_advance(uint32_t tlli);

View File

@ -156,8 +156,7 @@ static struct msgb *sched_select_ctrl_msg(struct gprs_rlcmac_bts *bts,
return msg;
}
/* schedule PACKET PAGING REQUEST */
if (!llist_empty(&pdch->paging_list))
msg = gprs_rlcmac_send_packet_paging_request(pdch);
msg = pdch->packet_paging_request();
if (msg) {
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling paging request "
"message at RTS for (TRX=%d, TS=%d)\n", trx, ts);