pespin has uploaded this change for review.

View Change

rlcmac: dl_tbf: Improve logic requesting a new UL TBF

Change-Id: I702872ba32a410bb5f09943af3cdadca482562db
---
M include/osmocom/gprs/rlcmac/gre.h
M src/rlcmac/gre.c
M src/rlcmac/rlcmac_enc.c
M src/rlcmac/tbf_ul.c
M tests/rlcmac/rlcmac_prim_test.c
M tests/rlcmac/rlcmac_prim_test.err
M tests/rlcmac/rlcmac_prim_test.ok
7 files changed, 147 insertions(+), 4 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/76/31576/1
diff --git a/include/osmocom/gprs/rlcmac/gre.h b/include/osmocom/gprs/rlcmac/gre.h
index ca5f773..f6397a6 100644
--- a/include/osmocom/gprs/rlcmac/gre.h
+++ b/include/osmocom/gprs/rlcmac/gre.h
@@ -20,6 +20,10 @@
struct gprs_rlcmac_entity *gprs_rlcmac_entity_alloc(uint32_t tlli);
void gprs_rlcmac_entity_free(struct gprs_rlcmac_entity *gre);

+bool gprs_rlcmac_entity_in_packet_idle_mode(const struct gprs_rlcmac_entity *gre);
+bool gprs_rlcmac_entity_in_packet_transfer_mode(const struct gprs_rlcmac_entity *gre);
+bool gprs_rlcmac_entity_have_tx_data_queued(const struct gprs_rlcmac_entity *gre);
+
int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_pdu, unsigned int ll_pdu_len,
enum osmo_gprs_rlcmac_llc_sapi sapi, uint8_t radio_prio);

diff --git a/src/rlcmac/gre.c b/src/rlcmac/gre.c
index 40cd585..53d53c7 100644
--- a/src/rlcmac/gre.c
+++ b/src/rlcmac/gre.c
@@ -66,6 +66,40 @@
talloc_free(gre);
}

+/* TS 44.060 5.3 In packet idle mode:
+* - no temporary block flow (TBF) exists..
+* - the mobile station monitors the relevant paging subchannels on CCCH. In packet
+* idle mode, upper layers may require the transfer of a upper layer PDU, which
+* implicitly triggers the establishment of a TBF and the transition to packet
+* transfer mode. In packet idle mode, upper layers may require the establishment
+* of an RR connection. When the mobile station enters dedicated mode (see 3GPP TS
+* 44.018), it may leave the packet idle mode, if the mobile station limitations
+* make it unable to handle the RR connection and the procedures in packet idle
+* mode simultaneously.*/
+bool gprs_rlcmac_entity_in_packet_idle_mode(const struct gprs_rlcmac_entity *gre)
+{
+ return !gre->ul_tbf && !gre->dl_tbf;
+}
+
+/* TS 44.060 5.4 "In packet transfer mode, the mobile station is allocated radio
+* resources providing one or more TBFs. [...]
+* When a transfer of upper layer PDUs
+* terminates, in either downlink or uplink direction, the corresponding TBF is
+* released. In packet transfer mode, when all TBFs have been released, in downlink
+* and uplink direction, the mobile station returns to packet idle mode."
+*/
+bool gprs_rlcmac_entity_in_packet_transfer_mode(const struct gprs_rlcmac_entity *gre)
+{
+ return gre->ul_tbf || gre->dl_tbf;
+}
+
+/* Whether MS has data queued from upper layers waiting to be transmitted in the
+ * Tx queue (an active UL TBF may still have some extra data) */
+bool gprs_rlcmac_entity_have_tx_data_queued(const struct gprs_rlcmac_entity *gre)
+{
+ return gprs_rlcmac_llc_queue_size(gre->llc_queue) > 0;
+}
+
int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_pdu, unsigned int ll_pdu_len,
enum osmo_gprs_rlcmac_llc_sapi sapi, uint8_t radio_prio)
{
@@ -75,7 +109,11 @@
if (rc < 0)
return rc;

- if (!gre->ul_tbf) {
+ /* TS 44.060 5.3 "In packet idle mode, upper layers may require the
+ * transfer of a upper layer PDU, which implicitly triggers the
+ * establishment of a TBF and the transition to packet transfer mode." */
+ if (gprs_rlcmac_entity_in_packet_idle_mode(gre)) {
+ OSMO_ASSERT(!gre->ul_tbf);
/* We have new data in the queue but we have no ul_tbf. Allocate one and start UL Assignment. */
gre->ul_tbf = gprs_rlcmac_ul_tbf_alloc(gre);
if (!gre->ul_tbf)
diff --git a/src/rlcmac/rlcmac_enc.c b/src/rlcmac/rlcmac_enc.c
index 6bceb8d..94f85f2 100644
--- a/src/rlcmac/rlcmac_enc.c
+++ b/src/rlcmac/rlcmac_enc.c
@@ -395,8 +395,9 @@
ack->DOWNLINK_TFI = dl_tbf->cur_alloc.dl_tfi;
gprs_rlcmac_enc_prepare_pkt_ack_nack_desc_gprs(&ack->Ack_Nack_Description, dl_tbf);

- /* Channel Request Description */
- if (gre->ul_tbf && gprs_rlcmac_tbf_ul_ass_pending(gre->ul_tbf)) {
+ /* Channel Request Description. Request a UL-TBF if we have UL data
+ * queued to send and no active UL BF (TS 44.060 8.1.2.5) */
+ if (!gre->ul_tbf && gprs_rlcmac_entity_have_tx_data_queued(gre)) {
Channel_Request_Description_t *chan_req = &ack->Channel_Request_Description;
ack->Exist_Channel_Request_Description = 1;
chan_req->PEAK_THROUGHPUT_CLASS = 0; /* TODO */
diff --git a/src/rlcmac/tbf_ul.c b/src/rlcmac/tbf_ul.c
index fbef343..e73b7f7 100644
--- a/src/rlcmac/tbf_ul.c
+++ b/src/rlcmac/tbf_ul.c
@@ -329,7 +329,7 @@
bool gprs_rlcmac_ul_tbf_have_data(const struct gprs_rlcmac_ul_tbf *ul_tbf)
{
return (ul_tbf->llc_tx_msg && msgb_length(ul_tbf->llc_tx_msg) > 0) ||
- (gprs_rlcmac_llc_queue_size(ul_tbf->tbf.gre->llc_queue) > 0);
+ gprs_rlcmac_entity_have_tx_data_queued(ul_tbf->tbf.gre);
}

bool gprs_rlcmac_ul_tbf_shall_keep_open(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi)
diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c
index 02ee04c..bbd7dcd 100644
--- a/tests/rlcmac/rlcmac_prim_test.c
+++ b/tests/rlcmac/rlcmac_prim_test.c
@@ -825,6 +825,7 @@
cleanup_test();
}

+
/* PCU allocates a DL TBF through PCH ImmAss for MS (when in packet-idle) */
static void test_dl_tbf_ccch_assign(void)
{
@@ -869,6 +870,59 @@
cleanup_test();
}

+/* PCU allocates a DL TBF through PCH ImmAss for MS (when in packet-idle). Then
+ * upper layers want to transmit more data so during DL ACK/NACK a new UL TBF is
+ * requested. */
+static void test_dl_tbf_ccch_assign_requests_ul_tbf_pacch(void)
+{
+ struct osmo_gprs_rlcmac_prim *rlcmac_prim;
+ int rc;
+ struct msgb *dl_data_msg;
+
+ printf("=== %s start ===\n", __func__);
+ prepare_test();
+ uint32_t tlli = 0x0000001;
+ uint8_t ts_nr = 7;
+ uint8_t usf = 0;
+ uint32_t rts_fn = 4;
+ uint8_t dl_tfi = 0;
+ uint8_t rrbp = GPRS_RLCMAC_RRBP_N_plus_17_18;
+
+ /* Notify RLCMAC about our TLLI */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_gmmrr_assign_req(tlli);
+ rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
+
+ OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_dl_tbf) == GSM_MACBLOCK_LEN);
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_dl_tbf);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* Transmit some DL LLC data MS<-PCU */
+ dl_data_msg = create_dl_data_block(dl_tfi, usf, GPRS_RLCMAC_CS_1, 0, true, true, rrbp);
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(ts_nr, rts_fn, 0, 0, 0,
+ msgb_data(dl_data_msg),
+ msgb_length(dl_data_msg));
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+ msgb_free(dl_data_msg);
+
+ /* Upper layers wants to transmit some payload, but no UL TBF exists yet: */
+ /* Submit 14 bytes to fit in 1 RLCMAC block to shorten test and end up in FINISHED state quickly: */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req, 14);
+ rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
+ rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* Trigger transmission of DL ACK/NACK, which should request a UL TBF in "Channel Request Description" */
+ rts_fn = rrbp2fn(rts_fn, rrbp);
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ printf("=== %s end ===\n", __func__);
+ cleanup_test();
+}
+
static const struct log_info_cat test_log_categories[] = { };
static const struct log_info test_log_info = {
.cat = test_log_categories,
@@ -899,6 +953,7 @@
test_ul_tbf_last_data_cv0_retrans_max();
test_ul_tbf_request_another_ul_tbf();
test_dl_tbf_ccch_assign();
+ test_dl_tbf_ccch_assign_requests_ul_tbf_pacch();

talloc_free(tall_ctx);
}
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index 0d8dd3a..d42a822 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -620,3 +620,33 @@
DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx DL ACK/NACK FinalAck=1
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) - V(N): "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR" R=Received I=Invalid
DLGLOBAL INFO DL_TBF{FINISHED}: Deallocated
+DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request
+DLGLOBAL INFO GMMRR-ASSIGN.req: creating new entity TLLI=0x00000001
+DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication
+DLGLOBAL INFO GRE(00000001) Got PCH IMM_ASS (DL_TBF): DL_TFI=0 TS=7
+DLGLOBAL INFO DL_TBF{NEW}: Allocated
+DLGLOBAL INFO DL_TBF{NEW}: Received Event DL_ASS_COMPL
+DLGLOBAL INFO TBF(DL:NR-0:TLLI-00000001) Send L1CTL-CF_DL_TBF.req dl_slotmask=0x80 dl_tfi=0
+DLGLOBAL INFO DL_TBF{NEW}: state_chg to FLOW
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Rx new DL data
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) DL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Got CS-1 RLC data block: FBI=1, BSN=0, SPB=0, S/P=1 RRBP=1, E=0, bitoffs=24
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) BSN 0 storing in window (0..63)
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) data_length=20, data=19 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+DLGLOBAL DEBUG - Raising V(R) to 1
+DLGLOBAL DEBUG - Taking block 0 out, raising V(Q) to 1
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Assembling frames: (len=20)
+DLGLOBAL DEBUG DL DATA LI contains extension octet: LI=6, M=0, E=1, count=0
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Frame 1 starts at offset 1, length=6, is_complete=1
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) complete UL frame len=6
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) No gaps in received block, last block: BSN=0 FBI=1
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Finished with DL TBF
+DLGLOBAL INFO DL_TBF{FLOW}: Received Event LAST_DL_DATA_RECVD
+DLGLOBAL INFO DL_TBF{FLOW}: state_chg to FINISHED
+DLGLOBAL DEBUG Register POLL (TS=7 FN=21, reason=DL_ACK)
+DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication
+DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx DL ACK/NACK FinalAck=1
+DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) - V(N): "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR" R=Received I=Invalid
+DLGLOBAL INFO DL_TBF{FINISHED}: Deallocated
diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok
index 9e913ed..3effeb3 100644
--- a/tests/rlcmac/rlcmac_prim_test.ok
+++ b/tests/rlcmac/rlcmac_prim_test.ok
@@ -117,3 +117,9 @@
test_rlcmac_prim_up_cb(): Rx GRR-UNITDATA.indication TLLI=0x00000001 ll=[43 c0 01 2b 2b 2b ]
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=23 data=[40 14 00 00 00 00 00 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ]
=== test_dl_tbf_ccch_assign end ===
+=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch start ===
+sys={0.000000}, mono={0.000000}: clock_override_set
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=0x80 dl_tfi=0
+test_rlcmac_prim_up_cb(): Rx GRR-UNITDATA.indication TLLI=0x00000001 ll=[43 c0 01 2b 2b 2b ]
+test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=23 data=[40 14 00 00 00 00 00 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ]
+=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch end ===

To view, visit change 31576. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I702872ba32a410bb5f09943af3cdadca482562db
Gerrit-Change-Number: 31576
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-MessageType: newchange