diff --git a/src/tbf_fsm.c b/src/tbf_fsm.c index 9ddbd69f..6fe2a7ac 100644 --- a/src/tbf_fsm.c +++ b/src/tbf_fsm.c @@ -45,6 +45,7 @@ const struct value_string tbf_fsm_event_names[] = { { TBF_EV_ASSIGN_READY_CCCH, "ASSIGN_READY_CCCH" }, { TBF_EV_ASSIGN_PCUIF_CNF, "ASSIGN_PCUIF_CNF" }, { TBF_EV_FIRST_UL_DATA_RECVD, "FIRST_UL_DATA_RECVD" }, + { TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS, "CONTENTION_RESOLUTION_MS_SUCCESS" }, { TBF_EV_DL_ACKNACK_MISS, "DL_ACKNACK_MISS" }, { TBF_EV_LAST_DL_DATA_SENT, "LAST_DL_DATA_SENT" }, { TBF_EV_LAST_UL_DATA_RECVD, "LAST_UL_DATA_RECVD" }, @@ -230,6 +231,10 @@ static void st_flow(struct osmo_fsm_inst *fi, uint32_t event, void *data) dl_tbf = NULL; } break; + case TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS: + OSMO_ASSERT(tbf_direction(ctx->tbf) == GPRS_RLCMAC_UL_TBF); + ul_tbf_contention_resolution_success(tbf_as_ul_tbf(ctx->tbf)); + break; case TBF_EV_DL_ACKNACK_MISS: OSMO_ASSERT(tbf_direction(ctx->tbf) == GPRS_RLCMAC_DL_TBF); /* DL TBF: we missed a DL ACK/NACK. If we started assignment @@ -279,6 +284,12 @@ static void st_finished(struct osmo_fsm_inst *fi, uint32_t event, void *data) bool new_ul_tbf_requested; switch (event) { + case TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS: + OSMO_ASSERT(tbf_direction(ctx->tbf) == GPRS_RLCMAC_UL_TBF); + /* UL TBF: If MS only sends 1 RLCMAC UL block, it can be that we + * end up in FINISHED state before sending the first UL ACK/NACK */ + ul_tbf_contention_resolution_success(tbf_as_ul_tbf(ctx->tbf)); + break; case TBF_EV_DL_ACKNACK_MISS: OSMO_ASSERT(tbf_direction(ctx->tbf) == GPRS_RLCMAC_DL_TBF); break; @@ -480,6 +491,7 @@ static struct osmo_fsm_state tbf_fsm_states[] = { [TBF_ST_FLOW] = { .in_event_mask = X(TBF_EV_FIRST_UL_DATA_RECVD) | + X(TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS) | X(TBF_EV_DL_ACKNACK_MISS) | X(TBF_EV_LAST_DL_DATA_SENT) | X(TBF_EV_LAST_UL_DATA_RECVD) | @@ -496,6 +508,7 @@ static struct osmo_fsm_state tbf_fsm_states[] = { }, [TBF_ST_FINISHED] = { .in_event_mask = + X(TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS) | X(TBF_EV_DL_ACKNACK_MISS) | X(TBF_EV_FINAL_ACK_RECVD) | X(TBF_EV_FINAL_UL_ACK_CONFIRMED) | diff --git a/src/tbf_fsm.h b/src/tbf_fsm.h index 903bcd70..0acd4e58 100644 --- a/src/tbf_fsm.h +++ b/src/tbf_fsm.h @@ -29,6 +29,7 @@ enum tbf_fsm_event { TBF_EV_ASSIGN_READY_CCCH, /* TBF Start Time timer triggered */ TBF_EV_ASSIGN_PCUIF_CNF, /* Transmission of IMM.ASS for DL TBF to the MS confirmed by BTS over PCUIF */ TBF_EV_FIRST_UL_DATA_RECVD, /* UL TBF: Received first UL data from MS. Equals to Contention Resolution completed on the network side */ + TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS, /* UL TBF: Contention resolution success at the mobile station side (first UL_ACK_NACK confirming TLLI is received at the MS) */ TBF_EV_DL_ACKNACK_MISS, /* DL TBF: We polled for DL ACK/NACK but we received none (POLL timeout) */ TBF_EV_LAST_DL_DATA_SENT, /* DL TBF sends RLCMAC block containing last DL avilable data buffered */ TBF_EV_LAST_UL_DATA_RECVD, /* UL TBF sends RLCMAC block containing last UL data (cv=0) */ diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 40129ec8..bd885b65 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -257,6 +257,7 @@ int gprs_rlcmac_ul_tbf::assemble_forward_llc(const gprs_rlc_data *_data) return 0; } +/* 3GPP TS 44.060 sec 7a.2.1 Contention Resolution */ void gprs_rlcmac_ul_tbf::contention_resolution_start() { /* 3GPP TS 44.018 sec 11.1.2 Timers on the network side: "This timer is @@ -274,20 +275,17 @@ void gprs_rlcmac_ul_tbf::contention_resolution_start() } void gprs_rlcmac_ul_tbf::contention_resolution_success() { - if (m_contention_resolution_done) - return; + /* now we must set this flag, so we are allowed to assign downlink + * TBF on PACCH. it is only allowed when TLLI is acknowledged + * (3GPP TS 44.060 sec 7.1.3.1). */ + m_contention_resolution_done = true; - /* 3GPP TS 44.060 sec 7a.2.1 Contention Resolution */ /* 3GPP TS 44.018 3.5.2.1.4 Packet access completion: The one phase packet access procedure is completed at a successful contention resolution. The mobile station has entered the packet transfer mode. Timer T3141 is stopped on the network side */ t_stop(T3141, "Contention resolution success (UL-TBF, CCCH)"); - /* now we must set this flag, so we are allowed to assign downlink - * TBF on PACCH. it is only allowed when TLLI is acknowledged. */ - m_contention_resolution_done = true; - bts_do_rate_ctr_inc(bts, CTR_IMMEDIATE_ASSIGN_UL_TBF_CONTENTION_RESOLUTION_SUCCESS); } diff --git a/src/tbf_ul_ack_fsm.c b/src/tbf_ul_ack_fsm.c index b0506d18..f6e7a0d6 100644 --- a/src/tbf_ul_ack_fsm.c +++ b/src/tbf_ul_ack_fsm.c @@ -89,8 +89,8 @@ static struct msgb *create_ul_ack_nack(const struct tbf_ul_ack_fsm_ctx *ctx, * on the mobile station side when the mobile station receives a * PACKET UPLINK ACK/NACK" */ - if (ms_tlli(ms) != GSM_RESERVED_TMSI) - ul_tbf_contention_resolution_success(ctx->tbf); + if (ms_tlli(ms) != GSM_RESERVED_TMSI && !ul_tbf_contention_resolution_done(ctx->tbf)) + osmo_fsm_inst_dispatch(tbf_state_fi(ul_tbf_as_tbf(ctx->tbf)), TBF_EV_CONTENTION_RESOLUTION_MS_SUCCESS, NULL); if (final) { tbf_set_polling(ul_tbf_as_tbf(tbf), new_poll_fn, d->ts, PDCH_ULC_POLL_UL_ACK); diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 1124462c..31e2a4c1 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -1912,6 +1912,7 @@ Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED)', TA=7 Got MS: TLLI = 0xf1223344, TA = 7 UL_ACK_TBF(UL-TFI_0){SCHED_UL_ACK}: Received Event CREATE_RLCMAC_MSG PDCH(bts=0,trx=0,ts=7) POLL scheduled at FN 2654167 + 17 = 2654184 +TBF(UL-TFI_0){FINISHED}: Received Event CONTENTION_RESOLUTION_MS_SUCCESS TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) stopping timer T3141 [Contention resolution success (UL-TBF, CCCH)] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) Scheduled UL Acknowledgement polling on PACCH (FN=2654184, TS=7) UL_ACK_TBF(UL-TFI_0){SCHED_UL_ACK}: state_chg to WAIT_ACK