pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31576 )
Change subject: rlcmac: dl_tbf: Improve logic requesting a new UL TBF ......................................................................
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 ===