aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.cpp34
-rw-r--r--src/encoding.cpp25
-rw-r--r--src/encoding.h3
-rw-r--r--src/gprs_rlcmac_sched.cpp9
-rw-r--r--src/tbf.cpp23
-rw-r--r--src/tbf.h2
-rw-r--r--tests/tbf/TbfTest.cpp24
-rw-r--r--tests/tbf/TbfTest.err24
-rw-r--r--tests/tbf/TbfTest.ok3
9 files changed, 135 insertions, 12 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 4e6b5e9..0668c2d 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -1077,16 +1077,23 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
}
/* check for channel request */
if (ack_nack->Exist_Channel_Request_Description) {
- LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
- "message, so we provide one:\n");
/* This call will register the new TBF with the MS on success */
- tbf_alloc_ul(bts_data(), tbf->trx->trx_no,
+ gprs_rlcmac_ul_tbf *ul_tbf = tbf_alloc_ul(bts_data(),
+ tbf->trx->trx_no,
tbf->ms_class(), tbf->ms()->egprs_ms_class(),
tbf->tlli(), tbf->ta(), tbf->ms());
- /* schedule uplink assignment */
- tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ /* schedule uplink assignment or reject*/
+ if (ul_tbf) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we provide one:\n");
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ } else {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we pacekt access reject:\n");
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ;
+ }
}
/* get measurements */
if (tbf->ms()) {
@@ -1179,16 +1186,23 @@ void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nac
/* check for channel request */
if (ack_nack->Exist_ChannelRequestDescription) {
- LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
- "message, so we provide one:\n");
/* This call will register the new TBF with the MS on success */
- tbf_alloc_ul(bts_data(), tbf->trx->trx_no,
+ gprs_rlcmac_ul_tbf *ul_tbf = tbf_alloc_ul(bts_data(),
+ tbf->trx->trx_no,
tbf->ms_class(), tbf->ms()->egprs_ms_class(),
tbf->tlli(), tbf->ta(), tbf->ms());
- /* schedule uplink assignment */
- tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ /* schedule uplink assignment or reject*/
+ if (ul_tbf) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we provide one:\n");
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ } else {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we send packet access reject:\n");
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ;
+ }
}
/* get measurements */
diff --git a/src/encoding.cpp b/src/encoding.cpp
index ca72b0f..e5a8605 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -1391,3 +1391,28 @@ Encoding::AppendResult Encoding::rlc_data_to_dl_append(
return AR_NEED_MORE_BLOCKS;
}
+
+/*
+ * Refer 44.060 version 7.27.0 Release 7
+ * section 7.1.3.2.1 On receipt of a PACKET RESOURCE REQUEST message
+ * 8.1.2.5 Establishment of uplink TBF
+ */
+void Encoding::write_packet_access_reject(
+ bitvec * dest, uint32_t tlli)
+{
+ unsigned wp = 0;
+
+ bitvec_write_field(dest, wp, 0x1, 2); // Payload Type
+ bitvec_write_field(dest, wp, 0x0, 2); // Uplink block with TDMA FN
+ bitvec_write_field(dest, wp, 0, 1); // No Polling Bit
+ bitvec_write_field(dest, wp, 0x0, 3); // Uplink state flag
+ bitvec_write_field(dest, wp,
+ MT_PACKET_ACCESS_REJECT, 6); // MESSAGE TYPE
+ bitvec_write_field(dest, wp, 0, 2); // fixed 00
+ bitvec_write_field(dest, wp, 0x0, 1); // TLLI / G-RNTI : bit (32)
+ bitvec_write_field(dest, wp, tlli, 32); // CONTENTION_RESOLUTION_TLLI
+ bitvec_write_field(dest, wp, 1, 1); // WAIT_INDICATION size in seconds
+ /* TODO: make it configurable */
+ bitvec_write_field(dest, wp, 5, 8); // WAIT_INDICATION value
+ bitvec_write_field(dest, wp, 0, 1); // WAIT_INDICATION size in seconds
+}
diff --git a/src/encoding.h b/src/encoding.h
index 79dc32d..6164b89 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -74,6 +74,9 @@ public:
static void encode_rbb(const char *show_rbb, uint8_t *rbb);
+ static void write_packet_access_reject(
+ bitvec * dest, uint32_t tlli);
+
static void write_packet_uplink_ack(
struct gprs_rlcmac_bts *bts, bitvec * dest,
struct gprs_rlcmac_ul_tbf *tbf, bool is_final,
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index f486075..a3723df 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -72,7 +72,8 @@ static uint32_t sched_poll(BTS *bts,
*poll_tbf = dl_tbf;
if (dl_tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
*dl_ass_tbf = dl_tbf;
- if (dl_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
+ if (dl_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS
+ || dl_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)
*ul_ass_tbf = dl_tbf;
}
@@ -137,7 +138,11 @@ static struct msgb *sched_select_ctrl_msg(
*/
if (tbf == ul_ass_tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
- msg = ul_ass_tbf->create_ul_ass(fn, ts);
+ if (tbf->ul_ass_state ==
+ 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)
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 0ac8ace..2d82727 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -1013,6 +1013,29 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
return msg;
}
+struct msgb *gprs_rlcmac_tbf::create_packet_access_reject()
+{
+ struct msgb *msg;
+
+ msg = msgb_alloc(23, "rlcmac_ul_ass_rej");
+
+ bitvec *packet_access_rej = bitvec_alloc(23);
+
+ bitvec_unhex(packet_access_rej,
+ "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+
+ Encoding::write_packet_access_reject(
+ packet_access_rej, tlli());
+
+ bitvec_pack(packet_access_rej, msgb_put(msg, 23));
+
+ bitvec_free(packet_access_rej);
+ ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
+
+ return msg;
+
+}
+
struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn, uint8_t ts)
{
struct msgb *msg;
diff --git a/src/tbf.h b/src/tbf.h
index 3205f6e..e044053 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -64,6 +64,7 @@ enum gprs_rlcmac_tbf_dl_ass_state {
enum gprs_rlcmac_tbf_ul_ass_state {
GPRS_RLCMAC_UL_ASS_NONE = 0,
GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
+ GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
};
@@ -103,6 +104,7 @@ struct gprs_rlcmac_tbf {
struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
+ struct msgb *create_packet_access_reject();
GprsMs *ms() const;
void set_ms(GprsMs *ms);
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index 339390b..213bd12 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -2831,6 +2831,29 @@ const struct log_info debug_log_info = {
ARRAY_SIZE(default_categories),
};
+void test_packet_access_rej_epdan()
+{
+ BTS the_bts;
+ uint32_t tlli = 0xffeeddcc;
+
+ printf("=== start %s ===\n", __func__);
+ setup_bts(&the_bts, 4);
+ static gprs_rlcmac_dl_tbf *dl_tbf = tbf_init(&the_bts, 1);
+
+ dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+
+ struct msgb *msg = dl_tbf->create_packet_access_reject();
+
+ printf("packet reject: %s\n",
+ osmo_hexdump(msg->data, 23));
+
+ OSMO_ASSERT(!strcmp(osmo_hexdump(msg->data, 23),
+ "40 84 7f f7 6e e6 41 4b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b "));
+ printf("=== end %s ===\n", __func__);
+
+}
+
+
int main(int argc, char **argv)
{
struct vty_app_info pcu_vty_info = {0};
@@ -2874,6 +2897,7 @@ int main(int argc, char **argv)
test_tbf_li_decoding();
test_tbf_epdan_out_of_rx_window();
test_immediate_assign_rej();
+ test_packet_access_rej_epdan();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err
index 627cdc3..a680812 100644
--- a/tests/tbf/TbfTest.err
+++ b/tests/tbf/TbfTest.err
@@ -6846,3 +6846,27 @@ MS requests single block allocation
No PDCH available.
No PDCH resource for single block allocation.sending Immediate Assignment Uplink (AGCH) reject
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=4d 06 3a 10 70 8b 29 14 70 8b 29 14 70 8b 29 14 70 8b 29 14 0b 2b 2b
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Slot Allocation (Algorithm A) for class 11
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 10
+Modifying MS object, TLLI = 0x00000000, TA 220 -> 0
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
diff --git a/tests/tbf/TbfTest.ok b/tests/tbf/TbfTest.ok
index f921dfc..dc07fc7 100644
--- a/tests/tbf/TbfTest.ok
+++ b/tests/tbf/TbfTest.ok
@@ -72,3 +72,6 @@ Testing retx for MCS 6 to reseg_mcs 3
=== end test_immediate_assign_rej_multi_block ===
=== start test_immediate_assign_rej_single_block ===
=== end test_immediate_assign_rej_single_block ===
+=== start test_packet_access_rej_epdan ===
+packet reject: 40 84 7f f7 6e e6 41 4b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+=== end test_packet_access_rej_epdan ===