diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 12fd99fa..ed5003c9 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -711,7 +711,7 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) is_final = llc_queue_size(llc_queue()) == 0 && !keep_open(fn); if (is_final) { rdbi->cv = 0; - TBF_SET_STATE(this, TBF_ST_FINISHED); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_LAST_DL_DATA_SENT, NULL); } if (mcs_is_edge(cs)) { @@ -756,7 +756,7 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) if (is_final) { request_dl_ack(); - TBF_SET_STATE(this, TBF_ST_FINISHED); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_LAST_DL_DATA_SENT, NULL); } /* dequeue next LLC frame, if any */ diff --git a/src/tbf_fsm.c b/src/tbf_fsm.c index 5799d906..8e0649da 100644 --- a/src/tbf_fsm.c +++ b/src/tbf_fsm.c @@ -46,6 +46,8 @@ const struct value_string tbf_fsm_event_names[] = { { TBF_EV_ASSIGN_DEL_CCCH, "ASSIGN_DEL_CCCH" }, { TBF_EV_ASSIGN_ACK_PACCH, "ASSIGN_ACK_PACCH" }, { TBF_EV_ASSIGN_READY_CCCH, "ASSIGN_READY_CCCH" }, + { TBF_EV_LAST_DL_DATA_SENT, "LAST_DL_DATA_SENT" }, + { TBF_EV_LAST_UL_DATA_RECVD, "LAST_UL_DATA_RECVD" }, { 0, NULL } }; @@ -137,6 +139,19 @@ static void st_assign(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } +static void st_flow(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case TBF_EV_LAST_DL_DATA_SENT: + case TBF_EV_LAST_UL_DATA_RECVD: + /* All data has been sent or received, change state to FINISHED */ + tbf_fsm_state_chg(fi, TBF_ST_FINISHED); + break; + default: + OSMO_ASSERT(0); + } +} + static void tbf_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) { /* TODO: needed ? @@ -180,12 +195,14 @@ static struct osmo_fsm_state tbf_fsm_states[] = { }, [TBF_ST_FLOW] = { .in_event_mask = - 0, + X(TBF_EV_LAST_DL_DATA_SENT) | + X(TBF_EV_LAST_UL_DATA_RECVD), .out_state_mask = X(TBF_ST_FINISHED) | X(TBF_ST_WAIT_RELEASE) | X(TBF_ST_RELEASING), .name = "FLOW", + .action = st_flow, }, [TBF_ST_FINISHED] = { .in_event_mask = diff --git a/src/tbf_fsm.h b/src/tbf_fsm.h index a3050c07..ea0f58d1 100644 --- a/src/tbf_fsm.h +++ b/src/tbf_fsm.h @@ -32,6 +32,8 @@ enum tbf_fsm_event { TBF_EV_ASSIGN_DEL_CCCH, /* An assignment previously sent over CCCH has been confirmed by MS */ TBF_EV_ASSIGN_ACK_PACCH, /* We received a CTRL ACK confirming assignment started on PACCH */ TBF_EV_ASSIGN_READY_CCCH, /* TBF Start Time timer triggered */ + 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) */ }; enum tbf_fsm_states { diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 2874fc63..3eec555d 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -536,7 +536,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged( rdbi->bsn, rdbi->cv); if (rdbi->cv == 0) { LOGPTBFUL(this, LOGL_DEBUG, "Finished with UL TBF\n"); - TBF_SET_STATE(this, TBF_ST_FINISHED); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_LAST_UL_DATA_RECVD, NULL); /* Reset N3103 counter. */ this->n_reset(N3103); } diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 84735aaa..ccfd459d 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -483,6 +483,7 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Sending new dummy block at BSN 21, TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Empty chunk, added LLC dummy command of size 19, drained_since=112 TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Keep idle TBF open: 112/43 -> no TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Complete DL frame, len=19 +TBF(DL-TFI_0){FLOW}: Received Event LAST_DL_DATA_SENT TBF(DL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED) data block (BSN 21, CS-1): 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED) need_padding 0 spb_status 0 spb 0 (BSN1 21 BSN2 -1) @@ -1597,6 +1598,7 @@ MSG = 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==2) mcs_mode_restrict=EGPRS TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=FLOW) Sending new block at BSN 2, CS=CS-1 TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=FLOW) Complete DL frame, len=19 +TBF(DL-TFI_0){FLOW}: Received Event LAST_DL_DATA_SENT TBF(DL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=FINISHED) data block (BSN 2, CS-1): 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=FINISHED) need_padding 0 spb_status 0 spb 0 (BSN1 2 BSN2 -1) @@ -1649,6 +1651,7 @@ LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) len=16 No bctx TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) No gaps in received block, last block: BSN=0 CV=0 TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Finished with UL TBF +TBF(UL-TFI_0){FLOW}: Received Event LAST_UL_DATA_RECVD TBF(UL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) Scheduling Ack/Nack, because TLLI is included. TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) Scheduling final Ack/Nack, because all data was received and last block has CV==0. @@ -1889,6 +1892,7 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0) mcs_m TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Sending new block at BSN 0, CS=CS-4 TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Dequeue next LLC (len=10) TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Complete DL frame, len=10 +TBF(DL-TFI_0){FLOW}: Received Event LAST_DL_DATA_SENT TBF(DL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) data block (BSN 0, CS-4): 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) need_padding 0 spb_status 0 spb 0 (BSN1 0 BSN2 -1) @@ -2308,6 +2312,7 @@ LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) len=16 No bctx TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) No gaps in received block, last block: BSN=0 CV=0 TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Finished with UL TBF +TBF(UL-TFI_0){FLOW}: Received Event LAST_UL_DATA_RECVD TBF(UL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) Scheduling Ack/Nack, because TLLI is included. TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED) Scheduling final Ack/Nack, because all data was received and last block has CV==0. @@ -2988,6 +2993,7 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Sending new block at BSN 27, CS=CS- TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Complete DL frame, len=13 TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Dequeue next LLC (len=13) TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Complete DL frame, len=13 +TBF(DL-TFI_0){FLOW}: Received Event LAST_DL_DATA_SENT TBF(DL-TFI_0){FLOW}: state_chg to FINISHED TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) data block (BSN 27, CS-1): 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39 TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) need_padding 0 spb_status 0 spb 0 (BSN1 27 BSN2 -1) @@ -3332,6 +3338,7 @@ PDCH(bts=0,trx=0,ts=7) FN=2654448 Scheduling data message at RTS for DL TFI=1 pr TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10) mcs_mode_restrict=EGPRS TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) Sending new block at BSN 10, CS=CS-1 TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) Complete DL frame, len=21 +TBF(DL-TFI_1){FLOW}: Received Event LAST_DL_DATA_SENT TBF(DL-TFI_1){FLOW}: state_chg to FINISHED TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FINISHED) data block (BSN 10, CS-1): 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29 TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FINISHED) need_padding 0 spb_status 0 spb 0 (BSN1 10 BSN2 -1)