pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31446 )
Change subject: rlcmac: Use finished UL TBF to request a new one after Final UL ACK/NACK ......................................................................
rlcmac: Use finished UL TBF to request a new one after Final UL ACK/NACK
Change-Id: I4eb873250f5ee7eafb5b6126382ce088091d0447 --- M include/osmocom/gprs/rlcmac/tbf_ul.h M include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h M include/osmocom/gprs/rlcmac/tbf_ul_fsm.h M src/rlcmac/sched.c M src/rlcmac/tbf_ul.c M src/rlcmac/tbf_ul_ass_fsm.c M src/rlcmac/tbf_ul_fsm.c M tests/rlcmac/rlcmac_prim_test.c M tests/rlcmac/rlcmac_prim_test.err M tests/rlcmac/rlcmac_prim_test.ok 10 files changed, 289 insertions(+), 15 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/rlcmac/tbf_ul.h b/include/osmocom/gprs/rlcmac/tbf_ul.h index 32d7036..3382778 100644 --- a/include/osmocom/gprs/rlcmac/tbf_ul.h +++ b/include/osmocom/gprs/rlcmac/tbf_ul.h @@ -47,6 +47,8 @@
bool gprs_rlcmac_ul_tbf_in_contention_resolution(const struct gprs_rlcmac_ul_tbf *ul_tbf); unsigned int gprs_rlcmac_ul_tbf_n3104_max(const struct gprs_rlcmac_ul_tbf *ul_tbf); +bool gprs_rlcmac_ul_tbf_have_data(const struct gprs_rlcmac_ul_tbf *ul_tbf); +bool gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(const struct gprs_rlcmac_ul_tbf *ul_tbf); bool gprs_rlcmac_ul_tbf_data_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi); bool gprs_rlcmac_ul_tbf_dummy_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi);
diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h index d1159d5..4a1658d 100644 --- a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h +++ b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h @@ -46,6 +46,7 @@
enum tbf_ul_ass_fsm_event { GPRS_RLCMAC_TBF_UL_ASS_EV_START, /* Start Uplink assignment (data: enum gprs_rlcmac_tbf_ul_ass_type) */ + GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, /* Start Uplink assignment directly into 2phase from an older UL TBF */ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, /* (data: struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx *) */ GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, /* Generate RLC/MAC block (data: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, /* (data: decoded PktUlAss) */ @@ -71,6 +72,7 @@ void gprs_rlcmac_tbf_ul_ass_fsm_destructor(struct gprs_rlcmac_ul_tbf *ul_tbf);
int gprs_rlcmac_tbf_ul_ass_start(struct gprs_rlcmac_ul_tbf *ul_tbf, enum gprs_rlcmac_tbf_ul_ass_type type); +int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf, struct gprs_rlcmac_ul_tbf *old_ul_tbf); bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf); bool gprs_rlcmac_tbf_ul_ass_match_rach_req(struct gprs_rlcmac_ul_tbf *ul_tbf, uint8_t ra); bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi); diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h index acee6f1..cfdb677 100644 --- a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h +++ b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h @@ -11,7 +11,8 @@ GPRS_RLCMAC_TBF_UL_ST_NEW = 0, /* new created TBF */ GPRS_RLCMAC_TBF_UL_ST_WAIT_ASSIGN, /* wait for Immediate Assignment */ GPRS_RLCMAC_TBF_UL_ST_FLOW, /* RLC/MAC flow, resource needed */ - GPRS_RLCMAC_TBF_UL_ST_FINISHED, /* flow finished, wait for release */ + GPRS_RLCMAC_TBF_UL_ST_FINISHED, /* All data transmitted (CV=0), only retransmits and waiting for ACKs */ + GPRS_RLCMAC_TBF_UL_ST_RELEASING, /* Network sent UL ACK w/ FinalAck=1 and polled for response */ };
struct gprs_rlcmac_tbf_ul_fsm_ctx { @@ -24,6 +25,10 @@ unsigned int pkt_acc_proc_attempts; /* 9.3.3.3.2: The block with CV=0 shall not be retransmitted more than four times. */ unsigned int last_data_block_retrans_attempts; + /* Whether the Received Packet UL ACK/NACK w/ FinalAck=1 had 'TBF Est' field to '1'. + * Used during ST_RELEASING to find out if a new UL TBF can be recreated + * when ansering the final UL ACK. */ + bool rx_final_pkt_ul_ack_nack_has_tbf_est; };
enum tbf_ul_fsm_event { @@ -33,7 +38,7 @@ GPRS_RLCMAC_TBF_UL_EV_N3104_MAX, GPRS_RLCMAC_TBF_UL_EV_CONTENTION_RESOLUTION_SUCCESS, GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT, - GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, + GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, /* data: bool TBF_EST */ };
int gprs_rlcmac_tbf_ul_fsm_init(void); diff --git a/src/rlcmac/sched.c b/src/rlcmac/sched.c index 5a3fae8..b5c02cc 100644 --- a/src/rlcmac/sched.c +++ b/src/rlcmac/sched.c @@ -34,6 +34,7 @@ struct tbf_sched_ctrl_candidates { struct gprs_rlcmac_dl_tbf *poll_dl_ack_final_ack; /* 8.1.2.2 1) */ struct gprs_rlcmac_dl_tbf *poll_dl_ack; /* 8.1.2.2 7) */ + struct gprs_rlcmac_ul_tbf *poll_ul_ack_new_ul_tbf; /* 9.3.2.4.2 (answer with PKT RES REQ) */ struct gprs_rlcmac_ul_tbf *poll_ul_ack; /* 11.2.2 (answer with PKT CTRL ACK) */ struct gprs_rlcmac_ul_tbf *ul_ass; }; @@ -89,8 +90,26 @@ /* TODO */ break; case GPRS_RLCMAC_PDCH_ULC_POLL_UL_ACK: + /* TS 44.060: 9.3.2.4.2 If the PACKET UPLINK ACK/NACK message + * has the Final Ack Indicator bit set to '1' and the following + * conditions are fulfilled: TBF Est field is set to '1'; the + * mobile station has new data to transmit; the mobile station + * has no other ongoing downlink TBFs, the mobile station shall + * release the uplink TBF and may request the establishment of a + * new TBF using one of the following procedures. + * If Control Ack Type parameter in System Information indicates + * acknowledgement is RLC/MAC control block, the mobile station + * shall transmit the PACKET RESOURCE REQUEST message and start + * timer T3168 for the TBF request. The mobile station shall use + * the same procedures as are used for TBF establishment using two + * phase access described in sub-clause 7.1.3 starting from the + * point where the mobile station transmits the PACKET RESOURCE + * REQUEST message. */ ul_tbf = tbf_as_ul_tbf(node->tbf); - tbfs->poll_ul_ack = ul_tbf; + if (gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(ul_tbf)) + tbfs->poll_ul_ack_new_ul_tbf = ul_tbf; + else + tbfs->poll_ul_ack = ul_tbf; break; case GPRS_RLCMAC_PDCH_ULC_POLL_DL_ACK: dl_tbf = tbf_as_dl_tbf(node->tbf); @@ -148,6 +167,9 @@ struct tbf_sched_ctrl_candidates *tbfs) { struct msgb *msg = NULL; + struct gprs_rlcmac_entity *gre; + int rc; + /* 8.1.2.2 1) (EGPRS) PACKET DOWNLINK ACK/NACK w/ FinalAckInd=1 */ if (tbfs->poll_dl_ack_final_ack) { LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx DL ACK/NACK FinalAck=1\n", @@ -158,12 +180,36 @@ }
/* 8.1.2.2 5) Any other RLC/MAC control message, other than a (EGPRS) PACKET DOWNLINK ACK/NACK */ + if (tbfs->poll_ul_ack_new_ul_tbf) { + LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Resource Request (UL ACK/NACK poll)\n", + bi->ts, bi->fn, bi->usf); + gre = tbfs->poll_ul_ack_new_ul_tbf->tbf.gre; + OSMO_ASSERT(gre->ul_tbf == tbfs->poll_ul_ack_new_ul_tbf); + gre->ul_tbf = gprs_rlcmac_ul_tbf_alloc(gre); + if (!gre->ul_tbf) { + gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack_new_ul_tbf); + return NULL; + } + /* Prepare new UL TBF from old UL TBF: */ + rc = gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(gre->ul_tbf, tbfs->poll_ul_ack_new_ul_tbf); + gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack_new_ul_tbf); /* always free */ + if (rc < 0) { + gprs_rlcmac_ul_tbf_free(gre->ul_tbf); + return NULL; + } + /* New UL TBF is ready to send the Pkt Res Req: */ + OSMO_ASSERT(gprs_rlcmac_tbf_ul_ass_rts(gre->ul_tbf, bi)); + msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(gre->ul_tbf, bi); + if (msg) + return msg; + } if (tbfs->poll_ul_ack) { LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Control Ack (UL ACK/NACK poll)\n", bi->ts, bi->fn, bi->usf); msg = gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(tbfs->poll_ul_ack); - if (msg) - return msg; + /* Last UL message, freeing */ + gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack); + return msg; } if (tbfs->ul_ass) { msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, bi); diff --git a/src/rlcmac/tbf_ul.c b/src/rlcmac/tbf_ul.c index d3343d0..0b62610 100644 --- a/src/rlcmac/tbf_ul.c +++ b/src/rlcmac/tbf_ul.c @@ -123,6 +123,36 @@ return 3 * (bs_cv_max + 3) * ul_tbf->cur_alloc.num_ts; }
+/* Whether the existing UL TBF can directly request a new UL TBF instead of goig to packet idle mode. */ +bool gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(const struct gprs_rlcmac_ul_tbf *ul_tbf) +{ + /* 9.3.2.4.2: "If the PACKET UPLINK ACK/NACK message has the Final Ack Indicator + * bit set to '1' and the following conditions are fulfilled: TBF Est field is set + * to '1'; the mobile station has new data to transmit; the mobile station has no + * other ongoing downlink TBFs, the mobile station shall release the uplink TBF and + * may request the establishment of a new TBF" + */ + + /* "PACKET UPLINK ACK/NACK message has the Final Ack Indicator" means GPRS_RLCMAC_TBF_UL_ST_RELEASING: */ + if (gprs_rlcmac_tbf_ul_state(ul_tbf) != GPRS_RLCMAC_TBF_UL_ST_RELEASING) + return false; + + /* "TBF Est field is set to '1'"" */ + if (!ul_tbf->state_fsm.rx_final_pkt_ul_ack_nack_has_tbf_est) + return false; + + /* the mobile station has new data to transmit */ + if (!gprs_rlcmac_ul_tbf_have_data(ul_tbf)) + return false; + + /* "the mobile station has no other ongoing downlink TBFs */ + if (ul_tbf->tbf.gre->dl_tbf) + return false; + + return true; + +} + /* Used by the scheduler to find out whether an Uplink Dummy Control Block can be transmitted. If * true, it will potentially call gprs_rlcmac_ul_tbf_dummy_create() to generate a new dummy message to transmit. */ bool gprs_rlcmac_ul_tbf_dummy_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi) @@ -182,20 +212,22 @@ return 0; }
-int gprs_rlcmac_ul_tbf_handle_final_ack(struct gprs_rlcmac_ul_tbf *ul_tbf) +int gprs_rlcmac_ul_tbf_handle_final_ack(struct gprs_rlcmac_ul_tbf *ul_tbf, const RlcMacDownlink_t *dl_block) { int rc = 0; + bool tbf_est = false; + const PU_AckNack_GPRS_t *ack_gprs = &dl_block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct;
- osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, NULL); + if (ack_gprs->Exist_AdditionsR99) + tbf_est = ack_gprs->AdditionsR99.TBF_EST; + + osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, &tbf_est);
/* range V(A)..V(S)-1 */ //received = gprs_rlcmac_rlc_ul_window_count_unacked(ul_tbf->ulw); /* report all outstanding packets as received */ //gprs_rlcmac_received_lost(this, received, 0); gprs_rlcmac_rlc_ul_window_reset(ul_tbf->ulw); - - /* TODO: check for RRBP and attempt to create a new UL TBF if - * gprs_rlcmac_ul_tbf_have_data(ul_tbf) */ return rc; }
@@ -232,7 +264,7 @@
if (ack_desc->FINAL_ACK_INDICATION) { LOGPTBFUL(ul_tbf, LOGL_DEBUG, "Final ACK received.\n"); - rc = gprs_rlcmac_ul_tbf_handle_final_ack(ul_tbf); + rc = gprs_rlcmac_ul_tbf_handle_final_ack(ul_tbf, dl_block); } else if (gprs_rlcmac_tbf_ul_state(ul_tbf) && gprs_rlcmac_rlc_ul_window_window_empty(ul_tbf->ulw)) { LOGPTBFUL(ul_tbf, LOGL_NOTICE, diff --git a/src/rlcmac/tbf_ul_ass_fsm.c b/src/rlcmac/tbf_ul_ass_fsm.c index a382ab2..6169080 100644 --- a/src/rlcmac/tbf_ul_ass_fsm.c +++ b/src/rlcmac/tbf_ul_ass_fsm.c @@ -37,6 +37,7 @@
static const struct value_string tbf_ul_ass_fsm_event_names[] = { { GPRS_RLCMAC_TBF_UL_ASS_EV_START, "START" }, + { GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, "START_DIRECT_2PHASE" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, "RX_CCCH_IMM_ASS" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, "RX_PKT_UL_ASS" }, @@ -185,6 +186,11 @@ submit_rach_req(ctx); tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS); break; + case GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE: + osmo_fsm_inst_dispatch(ctx->ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_UL_ASS_START, NULL); + ctx->ass_type = GPRS_RLCMAC_TBF_UL_ASS_TYPE_2PHASE; + tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ); + break; default: OSMO_ASSERT(0); } @@ -279,9 +285,11 @@ static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = { [GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE] = { .in_event_mask = - X(GPRS_RLCMAC_TBF_UL_ASS_EV_START), + X(GPRS_RLCMAC_TBF_UL_ASS_EV_START) | + X(GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE), .out_state_mask = - X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS), + X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS) | + X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ), .name = "IDLE", .onenter = st_idle_on_enter, .action = st_idle, @@ -403,6 +411,19 @@ return rc; }
+/* A releasing TBF being polled is used to fill in 1phase access internally and +* switch the FSM to trigger the 2hpase directly (tx Pkt Res Req) */ +int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf, struct gprs_rlcmac_ul_tbf *old_ul_tbf) +{ + int rc; + memcpy(&ul_tbf->ul_ass_fsm.phase1_alloc, &old_ul_tbf->cur_alloc, + sizeof(ul_tbf->ul_ass_fsm.phase1_alloc)); + rc = osmo_fsm_inst_dispatch(ul_tbf->ul_ass_fsm.fi, + GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, + NULL); + return rc; +} + bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf) { return ul_tbf->ul_ass_fsm.fi->state != GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE; diff --git a/src/rlcmac/tbf_ul_fsm.c b/src/rlcmac/tbf_ul_fsm.c index 3ecb41d..cb7df60 100644 --- a/src/rlcmac/tbf_ul_fsm.c +++ b/src/rlcmac/tbf_ul_fsm.c @@ -196,12 +196,23 @@ } break; case GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD: + ctx->rx_final_pkt_ul_ack_nack_has_tbf_est = *((bool *)data); + tbf_ul_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ST_RELEASING); break; default: OSMO_ASSERT(0); } }
+static void st_releasing(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + //struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_fsm_ctx *)fi->priv; + switch (event) { + default: + OSMO_ASSERT(0); + } +} + static struct osmo_fsm_state tbf_ul_fsm_states[] = { [GPRS_RLCMAC_TBF_UL_ST_NEW] = { .in_event_mask = @@ -240,10 +251,17 @@ X(GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT) | X(GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD), .out_state_mask = - X(GPRS_RLCMAC_TBF_UL_ST_NEW), + X(GPRS_RLCMAC_TBF_UL_ST_NEW) | + X(GPRS_RLCMAC_TBF_UL_ST_RELEASING), .name = "FINISHED", .action = st_finished, }, + [GPRS_RLCMAC_TBF_UL_ST_RELEASING] = { + .in_event_mask = 0, + .out_state_mask = 0, + .name = "RELEASING", + .action = st_releasing, + }, };
static int tbf_ul_fsm_timer_cb(struct osmo_fsm_inst *fi) diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c index c9bd2ff..96cc6d9 100644 --- a/tests/rlcmac/rlcmac_prim_test.c +++ b/tests/rlcmac/rlcmac_prim_test.c @@ -520,6 +520,74 @@ cleanup_test(); }
+/* Test UL TBF requesting assignment of a new UL TBF through PACCH when + * answering UL ACK/NACK w/ FinalACK=1 */ +static void test_ul_tbf_request_another_ul_tbf(void) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + int rc; + + printf("=== %s start ===\n", __func__); + prepare_test(); + RlcMacDownlink_t dl_block; + PU_AckNack_GPRS_t *ack_gprs = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct; + Ack_Nack_Description_t *ack_desc = &ack_gprs->Ack_Nack_Description; + uint32_t tlli = 0x2342; + uint8_t ul_tfi = 0; + uint8_t ts_nr = 7; + uint8_t usf = 0; + uint32_t rts_fn = 4; + + /* Send only 14 data to feed it in 1 UL block and speed up test length: */ + 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(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN); + ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */ + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + + /* Trigger transmission of LLC data (GMM Attach) */ + 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); + + /* PCU acks it: */ + ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2); + ack_desc->STARTING_SEQUENCE_NUMBER = 1; + ack_desc->FINAL_ACK_INDICATION = 1; + ul_ack_nack_mark(ack_desc, 0, true); + ul_ack_nack_mark(ack_desc, 1, true); + /* TBF Est is set: */ + ack_gprs->Exist_AdditionsR99 = 1; + ack_gprs->AdditionsR99.TBF_EST = 1; + /* Final ACK has Poll set: */ + dl_block.SP = 1; + dl_block.RRBP = GPRS_RLCMAC_RRBP_N_plus_13; + rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* New data from upper layers arrive which needs to be transmitted. This + * will make UL_TBF request a new UL_TBF when triggered to answer the final + * UL ACK/NACK, because there's no active DL TBF: */ + 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); + + /* Trigger transmission of PKT RES REQ: */ + rts_fn = rrbp2fn(rts_fn, dl_block.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 void test_ul_tbf_t3164_timeout(void) { struct osmo_gprs_rlcmac_prim *rlcmac_prim; @@ -773,6 +841,7 @@ test_ul_tbf_t3166_timeout(); test_ul_tbf_n3104_timeout(); test_ul_tbf_last_data_cv0_retrans_max(); + test_ul_tbf_request_another_ul_tbf(); test_dl_tbf_ccch_assign();
talloc_free(tall_ctx); diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err index 1337c44..e84461f 100644 --- a/tests/rlcmac/rlcmac_prim_test.err +++ b/tests/rlcmac/rlcmac_prim_test.err @@ -53,12 +53,13 @@ DLGLOBAL INFO UL_TBF{FINISHED}: Contention resolution succeeded, stop T3166 DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Final ACK received. DLGLOBAL INFO UL_TBF{FINISHED}: Received Event FINAL_ACK_RECVD +DLGLOBAL INFO UL_TBF{FINISHED}: state_chg to RELEASING DLGLOBAL DEBUG Register POLL (TS=7 FN=21, reason=UL_ACK) DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx Pkt Control Ack (UL ACK/NACK poll) DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Tx Packet Control Ack DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated -DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated +DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly DLGLOBAL INFO UL_TBF{NEW}: Allocated @@ -471,6 +472,68 @@ DLGLOBAL NOTICE UL_TBF{FINISHED}: TBF establishment failure (Data block with CV=0 retransmit attempts=4) DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated +DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request +DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly +DLGLOBAL INFO UL_TBF{NEW}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START +DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START +DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Send RACH.req ra=0x7b +DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to WAIT_CCCH_IMM_ASS +DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication +DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: Received Event RX_CCCH_IMM_ASS +DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss initial CS=CS-2 +DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0 +DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED +DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL +DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80 +DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW +DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Sending new block at BSN 0, CS=CS-2 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Dequeue next LLC (len=14) +DLGLOBAL DEBUG -- Chunk with length 14 is less than remaining space (26): add length header to delimit LLC frame +DLGLOBAL DEBUG -- Final block, so we done. +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Complete UL frame, len=0 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) data block (BSN 0, CS-2): 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) need_padding 0 spb_status 0 spb 0 (BSN1 0 BSN2 -1) +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying 1 RLC blocks, 1 BSNs +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying data unit 0 (BSN 0) +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) msg block (BSN 0, CS-2): 00 00 00 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 +DLGLOBAL INFO UL_TBF{FLOW}: Received Event FIRST_UL_DATA_SENT +DLGLOBAL INFO UL_TBF{FLOW}: First UL block sent, stop T3164 +DLGLOBAL INFO UL_TBF{FLOW}: First UL block sent (1 phase access), start T3166 +DLGLOBAL INFO UL_TBF{FLOW}: Received Event LAST_UL_DATA_SENT +DLGLOBAL INFO UL_TBF{FLOW}: state_chg to FINISHED +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) N3104 inc (1) +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication +DLGLOBAL INFO TS=7 FN=4 Rx Pkt UL ACK/NACK +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Got GPRS UL ACK bitmap: SSN: 1, BSN 0 to 1 - 1 (1 blocks), "R" +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) ack: (BSN=0)"R"(BSN=0) R=ACK I=NACK +DLGLOBAL DEBUG - got ack for BSN=0 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) V(B): (V(A)=1)""(V(S)-1=0) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid +DLGLOBAL INFO UL_TBF{FINISHED}: Received Event CONTENTION_RESOLUTION_SUCCESS +DLGLOBAL INFO UL_TBF{FINISHED}: Contention resolution succeeded, stop T3166 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Final ACK received. +DLGLOBAL INFO UL_TBF{FINISHED}: Received Event FINAL_ACK_RECVD +DLGLOBAL INFO UL_TBF{FINISHED}: state_chg to RELEASING +DLGLOBAL DEBUG Register POLL (TS=7 FN=17, reason=UL_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=17,usf=0) Tx Pkt Resource Request (UL ACK/NACK poll) +DLGLOBAL INFO UL_TBF{NEW}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START_DIRECT_2PHASE +DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START +DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN +DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to SCHED_PKT_RES_REQ +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated +DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated +DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: Received Event CREATE_RLCMAC_MSG +DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: state_chg to WAIT_PKT_UL_ASS +DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: Deallocated +DLGLOBAL INFO UL_TBF{ASSIGN}: 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 diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok index bfe2598..fdd570f 100644 --- a/tests/rlcmac/rlcmac_prim_test.ok +++ b/tests/rlcmac/rlcmac_prim_test.ok @@ -95,6 +95,13 @@ RTS 3: FN=26 test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=26 ts=7 data_len=34 data=[00 00 02 1d 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ] === test_ul_tbf_last_data_cv0_retrans_max end === +=== test_ul_tbf_request_another_ul_tbf start === +sys={0.000000}, mono={0.000000}: clock_override_set +test_rlcmac_prim_down_cb(): Rx L1CTL-RACH.request ra=0x7b +test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80 +test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[00 00 00 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ] +test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=17 ts=7 data_len=23 data=[40 16 40 00 08 d0 a0 bc 00 00 00 00 00 00 70 00 38 00 00 2b 2b 2b 2b ] +=== test_ul_tbf_request_another_ul_tbf end === === test_dl_tbf_ccch_assign 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