mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-pcu.git
synced 2025-11-03 05:33:31 +00:00
Forward ETWS Primary Notification to MS
Receive an Application Information Request from the BTS via PCU interface. Construct a Packet Application Information message from it (3GPP TS 44.060 11.2.47) and send it to all MS with active TBF. The TTCN-3 test infrastructure to test this feature is not quite ready yet, so I've added C unit tests instead. Related: OS#4048 Change-Id: Ie35959f833f46bde5f2126314b6f96763f863b36
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
|
||||
#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */
|
||||
#define PCU_IF_MSG_SUSP_REQ 0x03 /* BTS forwards GPRS SUSP REQ to PCU */
|
||||
#define PCU_IF_MSG_APP_INFO_REQ 0x04 /* BTS asks PCU to transmit APP INFO via PACCH */
|
||||
#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */
|
||||
#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
|
||||
#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
|
||||
@@ -172,6 +173,13 @@ struct gsm_pcu_if_pag_req {
|
||||
uint8_t identity_lv[9];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BTS tells PCU to [once] send given application data via PACCH to all UE with active TBF */
|
||||
struct gsm_pcu_if_app_info_req {
|
||||
uint8_t application_type; /* 4bit field, see TS 44.060 11.2.47 */
|
||||
uint8_t len; /* length of data */
|
||||
uint8_t data[162]; /* random size choice; ETWS needs 56 bytes */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BTS tells PCU about a GPRS SUSPENSION REQUEST received on DCCH */
|
||||
struct gsm_pcu_if_susp_req {
|
||||
uint32_t tlli;
|
||||
@@ -198,6 +206,7 @@ struct gsm_pcu_if {
|
||||
struct gsm_pcu_if_act_req act_req;
|
||||
struct gsm_pcu_if_time_ind time_ind;
|
||||
struct gsm_pcu_if_pag_req pag_req;
|
||||
struct gsm_pcu_if_app_info_req app_info_req;
|
||||
} u;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -136,6 +136,8 @@ public:
|
||||
/* internal use */
|
||||
static void timeout(void *priv_);
|
||||
|
||||
bool app_info_pending;
|
||||
|
||||
protected:
|
||||
void update_status();
|
||||
GprsMs *ref();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
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;
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) -I$(top_srcdir)/src/ -I$(top_srcdir)/include/
|
||||
AM_LDFLAGS = -lrt -no-install
|
||||
|
||||
check_PROGRAMS = rlcmac/RLCMACTest alloc/AllocTest alloc/MslotTest tbf/TbfTest types/TypesTest ms/MsTest llist/LListTest llc/LlcTest codel/codel_test edge/EdgeTest bitcomp/BitcompTest fn/FnTest
|
||||
check_PROGRAMS = rlcmac/RLCMACTest alloc/AllocTest alloc/MslotTest tbf/TbfTest types/TypesTest ms/MsTest llist/LListTest llc/LlcTest codel/codel_test edge/EdgeTest bitcomp/BitcompTest fn/FnTest app_info/AppInfoTest
|
||||
noinst_PROGRAMS = emu/pcu_emu
|
||||
|
||||
rlcmac_RLCMACTest_SOURCES = rlcmac/RLCMACTest.cpp
|
||||
@@ -108,6 +108,14 @@ fn_FnTest_LDADD = \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(COMMON_LA)
|
||||
|
||||
app_info_AppInfoTest_SOURCES = app_info/AppInfoTest.cpp
|
||||
app_info_AppInfoTest_LDADD = \
|
||||
$(top_builddir)/src/libgprs.la \
|
||||
$(LIBOSMOGB_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(COMMON_LA)
|
||||
|
||||
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
|
||||
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||
:;{ \
|
||||
@@ -138,7 +146,8 @@ EXTRA_DIST = \
|
||||
llist/LListTest.ok llist/LListTest.err \
|
||||
codel/codel_test.ok \
|
||||
edge/EdgeTest.ok \
|
||||
fn/FnTest.ok
|
||||
fn/FnTest.ok \
|
||||
app_info/AppInfoTest.ok app_info/AppInfoTest.err
|
||||
|
||||
DISTCLEANFILES = atconfig
|
||||
|
||||
|
||||
191
tests/app_info/AppInfoTest.cpp
Normal file
191
tests/app_info/AppInfoTest.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/* Copyright (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <assert.h>
|
||||
#include "gprs_rlcmac.h"
|
||||
#include "bts.h"
|
||||
|
||||
extern "C" {
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/application.h>
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
gprs_rlcmac_dl_tbf *tbf1, *tbf2;
|
||||
GprsMs *ms1, *ms2;
|
||||
struct msgb *sched_app_info(struct gprs_rlcmac_tbf *tbf);
|
||||
|
||||
/* globals used by the code */
|
||||
void *tall_pcu_ctx;
|
||||
int16_t spoof_mnc = 0, spoof_mcc = 0;
|
||||
bool spoof_mnc_3_digits = false;
|
||||
|
||||
void test_enc_zero_len() {
|
||||
struct gsm_pcu_if_app_info_req req = {0, 0, {0}};
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
assert(gprs_rlcmac_app_info_msg(&req) == NULL);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void test_enc() {
|
||||
struct gsm_pcu_if_app_info_req req = {0, 15, {0xff, 0x00, 0xff}};
|
||||
const char *exp = "03 fc 03 fc 00 00 00 00 00 00 00 00 00 00 00 00 "; /* shifted by two bits to the right */
|
||||
struct msgb *msg;
|
||||
char *msg_dump;
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
msg = gprs_rlcmac_app_info_msg(&req);
|
||||
msg_dump = msgb_hexdump_c(tall_pcu_ctx, msg);
|
||||
|
||||
fprintf(stderr, "exp: %s\n", exp);
|
||||
fprintf(stderr, "msg: %s\n", msg_dump);
|
||||
assert(strcmp(msg_dump, exp) == 0);
|
||||
|
||||
msgb_free(msg);
|
||||
talloc_free(msg_dump);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void test_pcu_rx_no_subscr_with_active_tbf()
|
||||
{
|
||||
struct gsm_pcu_if pcu_prim = {PCU_IF_MSG_APP_INFO_REQ, };
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void prepare_bts_with_two_dl_tbf_subscr()
|
||||
{
|
||||
BTS *bts = BTS::main_bts();
|
||||
struct gprs_rlcmac_bts *bts_data;
|
||||
struct gprs_rlcmac_trx *trx;
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
|
||||
bts_data = bts->bts_data();
|
||||
bts_data->alloc_algorithm = alloc_algorithm_b;
|
||||
|
||||
trx = bts_data->trx;
|
||||
trx->pdch[4].enable();
|
||||
trx->pdch[5].enable();
|
||||
trx->pdch[6].enable();
|
||||
trx->pdch[7].enable();
|
||||
|
||||
ms1 = bts->ms_alloc(10, 11);
|
||||
tbf1 = tbf_alloc_dl_tbf(bts_data, ms1, 0, 10, 11, false);
|
||||
ms2 = bts->ms_alloc(12, 13);
|
||||
tbf2 = tbf_alloc_dl_tbf(bts_data, ms2, 0, 12, 13, false);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void test_sched_app_info_ok()
|
||||
{
|
||||
struct gsm_pcu_if pcu_prim = {PCU_IF_MSG_APP_INFO_REQ, };
|
||||
struct msgb *msg;
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
pcu_prim.u.app_info_req = {0, 15, {0xff, 0x00, 0xff}};
|
||||
pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim);
|
||||
|
||||
msg = sched_app_info(tbf1);
|
||||
assert(msg);
|
||||
msgb_free(msg);
|
||||
|
||||
msg = sched_app_info(tbf2);
|
||||
assert(msg);
|
||||
msgb_free(msg);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void test_sched_app_info_missing_app_info_in_bts()
|
||||
{
|
||||
struct gprs_rlcmac_bts *bts_data = BTS::main_bts()->bts_data();
|
||||
struct gsm_pcu_if pcu_prim = {PCU_IF_MSG_APP_INFO_REQ, };
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
pcu_prim.u.app_info_req = {0, 15, {0xff, 0x00, 0xff}};
|
||||
pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim);
|
||||
|
||||
msgb_free(bts_data->app_info);
|
||||
bts_data->app_info = NULL;
|
||||
|
||||
assert(sched_app_info(tbf1) == NULL);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void test_pcu_rx_overwrite_app_info()
|
||||
{
|
||||
struct gsm_pcu_if pcu_prim = {PCU_IF_MSG_APP_INFO_REQ, };
|
||||
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
pcu_prim.u.app_info_req = {0, 15, {0xff, 0x00, 0xff}};
|
||||
pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim);
|
||||
pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
fprintf(stderr, "--- %s ---\n", __func__);
|
||||
|
||||
BTS::main_bts()->cleanup();
|
||||
talloc_free(tbf1);
|
||||
talloc_free(tbf2);
|
||||
/* FIXME: talloc report disabled, because bts->ms_alloc() in prepare_bts_with_two_dl_tbf_subscr() causes leak */
|
||||
/* talloc_report_full(tall_pcu_ctx, stderr); */
|
||||
talloc_free(tall_pcu_ctx);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
tall_pcu_ctx = talloc_named_const(NULL, 1, "AppInfoTest");
|
||||
osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_parse_category_mask(osmo_stderr_target, "DL1IF,1:DRLCMAC,3:DRLCMACSCHED,1");
|
||||
|
||||
test_enc_zero_len();
|
||||
test_enc();
|
||||
test_pcu_rx_no_subscr_with_active_tbf();
|
||||
|
||||
prepare_bts_with_two_dl_tbf_subscr();
|
||||
test_sched_app_info_ok();
|
||||
test_sched_app_info_missing_app_info_in_bts();
|
||||
test_pcu_rx_overwrite_app_info();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/*
|
||||
* stubs that should not be reached
|
||||
*/
|
||||
extern "C" {
|
||||
void l1if_pdch_req() { abort(); }
|
||||
void l1if_connect_pdch() { abort(); }
|
||||
void l1if_close_pdch() { abort(); }
|
||||
void l1if_open_pdch() { abort(); }
|
||||
}
|
||||
50
tests/app_info/AppInfoTest.err
Normal file
50
tests/app_info/AppInfoTest.err
Normal file
@@ -0,0 +1,50 @@
|
||||
--- test_enc_zero_len ---
|
||||
Application Information Request with zero length received!
|
||||
|
||||
--- test_enc ---
|
||||
exp: 03 fc 03 fc 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
msg: 03 fc 03 fc 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
--- test_pcu_rx_no_subscr_with_active_tbf ---
|
||||
Application Information Request received: type=0x00000000 len=0
|
||||
Packet Application Information will not be sent, no subscribers with active TBF
|
||||
|
||||
--- prepare_bts_with_two_dl_tbf_subscr ---
|
||||
Creating MS object, TLLI = 0x00000000
|
||||
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 10
|
||||
Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
|
||||
[DL] algo B <multi> (suggested TRX: 0): using 4 slots
|
||||
PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
|
||||
PDCH(TS 5, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
|
||||
PDCH(TS 6, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
|
||||
PDCH(TS 7, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
|
||||
Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
|
||||
Creating MS object, TLLI = 0x00000000
|
||||
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 12
|
||||
Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 13
|
||||
[DL] algo B <multi> (suggested TRX: 0): using 3 slots
|
||||
PDCH(TS 4, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBFs, USFs = 00, TFIs = 00000003.
|
||||
PDCH(TS 5, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBFs, USFs = 00, TFIs = 00000003.
|
||||
PDCH(TS 6, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBFs, USFs = 00, TFIs = 00000003.
|
||||
Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL)
|
||||
|
||||
--- test_sched_app_info_ok ---
|
||||
Application Information Request received: type=0x00000000 len=15
|
||||
Sending Packet Application Information to 2 subscribers with active TBF
|
||||
Sending Packet Application Information message
|
||||
Sending Packet Application Information message
|
||||
Packet Application Information successfully sent to all MS with active TBF
|
||||
|
||||
--- test_sched_app_info_missing_app_info_in_bts ---
|
||||
Application Information Request received: type=0x00000000 len=15
|
||||
Sending Packet Application Information to 2 subscribers with active TBF
|
||||
MS has app_info_pending flag set, but no Packet Application Information message stored in BTS!
|
||||
|
||||
--- test_pcu_rx_overwrite_app_info ---
|
||||
Application Information Request received: type=0x00000000 len=15
|
||||
Sending Packet Application Information to 2 subscribers with active TBF
|
||||
Application Information Request received: type=0x00000000 len=15
|
||||
Previous Packet Application Information was not sent to all subscribers, overwriting with new one
|
||||
Sending Packet Application Information to 2 subscribers with active TBF
|
||||
|
||||
--- cleanup ---
|
||||
0
tests/app_info/AppInfoTest.ok
Normal file
0
tests/app_info/AppInfoTest.ok
Normal file
@@ -82,3 +82,10 @@ AT_KEYWORDS([fn])
|
||||
cat $abs_srcdir/fn/FnTest.ok > expout
|
||||
AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/fn/FnTest], [0], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([app_info])
|
||||
AT_KEYWORDS([app_info])
|
||||
cat $abs_srcdir/app_info/AppInfoTest.ok > expout
|
||||
cat $abs_srcdir/app_info/AppInfoTest.err > experr
|
||||
AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/app_info/AppInfoTest], [0], [expout], [experr])
|
||||
AT_CLEANUP
|
||||
|
||||
Reference in New Issue
Block a user