diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2021-07-22 19:20:50 +0200 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2021-08-23 17:14:21 +0200 |
commit | 33e80071002c3c0bf097a71c2c8e29d445304255 (patch) | |
tree | ef6a034fc74ca39cfe3f410bbf4d58da884615ee /src | |
parent | 88f34812dfbda0ae46ecc6d729d503604b346761 (diff) |
Move NULL and ASSIGN tbf_state transition to tbf_fsm
At some point later in time the state_flags will most probably be split
into different variables, one ending up in a different FSM. It is moved
so far to the exsiting FSM from the C++ class since it's easier to
access it from C and C++ code, and anyway that kind of information
belongs to the FSM.
Related: OS#2709
Change-Id: I3c62e9e83965cb28065338733f182863e54d7474
Diffstat (limited to 'src')
-rw-r--r-- | src/pcu_vty_functions.cpp | 10 | ||||
-rw-r--r-- | src/pdch.cpp | 5 | ||||
-rw-r--r-- | src/tbf.cpp | 39 | ||||
-rw-r--r-- | src/tbf.h | 69 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 16 | ||||
-rw-r--r-- | src/tbf_fsm.c | 108 | ||||
-rw-r--r-- | src/tbf_fsm.h | 5 | ||||
-rw-r--r-- | src/tbf_ul.cpp | 11 |
8 files changed, 144 insertions, 119 deletions
diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp index 0b83a68f..657e5a16 100644 --- a/src/pcu_vty_functions.cpp +++ b/src/pcu_vty_functions.cpp @@ -55,9 +55,9 @@ static void tbf_print_vty_info(struct vty *vty, struct gprs_rlcmac_tbf *tbf) tbf->direction == GPRS_RLCMAC_UL_TBF ? "UL" : "DL", tbf->imsi(), VTY_NEWLINE); vty_out(vty, " created=%lu state=%08x [CCCH:%u, PACCH:%u] 1st_TS=%d 1st_cTS=%d ctrl_TS=%d MS_CLASS=%d/%d%s", - tbf->created_ts(), tbf->state_flags, - tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH), - tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH), + tbf->created_ts(), tbf->state_fsm.state_flags, + tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH), + tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH), tbf->first_ts, tbf->first_common_ts, tbf->control_ts, tbf->ms_class(), @@ -113,7 +113,7 @@ int pcu_vty_show_tbf_all(struct vty *vty, struct gprs_rlcmac_bts *bts, uint32_t trx = &bts->trx[trx_no]; llist_for_each_entry(iter, &trx->ul_tbfs, list) { tbf = (struct gprs_rlcmac_tbf *)iter->entry; - if (tbf->state_flags & flags) + if (tbf->state_fsm.state_flags & flags) tbf_print_vty_info(vty, tbf); } } @@ -123,7 +123,7 @@ int pcu_vty_show_tbf_all(struct vty *vty, struct gprs_rlcmac_bts *bts, uint32_t trx = &bts->trx[trx_no]; llist_for_each_entry(iter, &trx->dl_tbfs, list) { tbf = (struct gprs_rlcmac_tbf *)iter->entry; - if (tbf->state_flags & flags) + if (tbf->state_fsm.state_flags & flags) tbf_print_vty_info(vty, tbf); } } diff --git a/src/pdch.cpp b/src/pdch.cpp index 2ec40ce1..f53e155d 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -368,12 +368,13 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, tbf->direction == new_tbf->direction) tbf_free(tbf); - if (new_tbf->check_n_clear(GPRS_RLCMAC_FLAG_CCCH)) { + if (new_tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)) { /* We now know that the PACCH really existed */ LOGPTBF(new_tbf, LOGL_INFO, "The TBF has been confirmed on the PACCH, " "changed type from CCCH to PACCH\n"); - TBF_ASS_TYPE_SET(new_tbf, GPRS_RLCMAC_FLAG_PACCH); + osmo_fsm_inst_dispatch(new_tbf->state_fsm.fi, TBF_EV_ASSIGN_DEL_CCCH, NULL); + osmo_fsm_inst_dispatch(new_tbf->state_fsm.fi, TBF_EV_ASSIGN_ADD_PACCH, NULL); } TBF_SET_STATE(new_tbf, TBF_ST_FLOW); /* stop pending assignment timer */ diff --git a/src/tbf.cpp b/src/tbf.cpp index fcad879f..8b17059a 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -120,7 +120,6 @@ gprs_rlcmac_tbf::Meas::Meas() : } gprs_rlcmac_tbf::gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir) : - state_flags(0), direction(dir), trx(NULL), first_ts(0), @@ -152,6 +151,7 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_ memset(&m_trx_list, 0, sizeof(m_trx_list)); m_trx_list.entry = this; + memset(&state_fsm, 0, sizeof(state_fsm)); state_fsm.tbf = this; state_fsm.fi = osmo_fsm_inst_alloc(&tbf_fsm, this, &state_fsm, LOGL_INFO, NULL); @@ -572,13 +572,14 @@ void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum pdch_ul { const char *chan = "UNKNOWN"; - if (state_flags & (1 << (GPRS_RLCMAC_FLAG_CCCH))) + if (state_fsm.state_flags & (1 << (GPRS_RLCMAC_FLAG_CCCH))) chan = "CCCH"; - if (state_flags & (1 << (GPRS_RLCMAC_FLAG_PACCH))) + if (state_fsm.state_flags & (1 << (GPRS_RLCMAC_FLAG_PACCH))) chan = "PACCH"; - if ((state_flags & (1 << (GPRS_RLCMAC_FLAG_PACCH))) && (state_flags & (1 << (GPRS_RLCMAC_FLAG_CCCH)))) + if ((state_fsm.state_flags & (1 << (GPRS_RLCMAC_FLAG_PACCH))) && + (state_fsm.state_flags & (1 << (GPRS_RLCMAC_FLAG_CCCH)))) LOGPTBFDL(this, LOGL_ERROR, "Attempt to schedule polling on %s (FN=%d, TS=%d) with both CCCH and PACCH flags set - FIXME!\n", chan, new_poll_fn, ts); @@ -648,11 +649,11 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_ } } else if (ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) { - if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) { + if (!(state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) { LOGPTBF(this, LOGL_NOTICE, "Timeout for polling PACKET CONTROL ACK for PACKET UPLINK ASSIGNMENT: %s\n", rlcmac_diag().c_str()); - state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS); + state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS); } ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_TIMEDOUT); @@ -667,11 +668,11 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_ /* reschedule UL assignment */ ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; } else if (dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) { - if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) { + if (!(state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) { LOGPTBF(this, LOGL_NOTICE, "Timeout for polling PACKET CONTROL ACK for PACKET DOWNLINK ASSIGNMENT: %s\n", rlcmac_diag().c_str()); - state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS); + state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS); } dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_TIMEDOUT); @@ -693,11 +694,11 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_ } else if (direction == GPRS_RLCMAC_DL_TBF) { gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(this); - if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) { + if (!(dl_tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) { LOGPTBF(this, LOGL_NOTICE, "Timeout for polling PACKET DOWNLINK ACK: %s\n", dl_tbf->rlcmac_diag().c_str()); - dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); + dl_tbf->state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); } if (dl_tbf->state_is(TBF_ST_RELEASING)) @@ -715,8 +716,8 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_ return; } /* resend IMM.ASS on CCCH on timeout */ - if ((dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)) - && !(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) { + if ((dl_tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)) + && !(dl_tbf->state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) { LOGPTBF(dl_tbf, LOGL_DEBUG, "Re-send dowlink assignment on PCH (IMSI=%s)\n", imsi()); /* send immediate assignment */ @@ -788,7 +789,7 @@ void gprs_rlcmac_tbf::handle_timeout() LOGPTBF(this, LOGL_DEBUG, "timer 0 expired. cur_fn=%d\n", current_fn); /* PACCH assignment timeout (see timers X2000, X2001) */ - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) { + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) { if (state_is(TBF_ST_ASSIGN)) { LOGPTBF(this, LOGL_NOTICE, "releasing due to PACCH assignment timeout.\n"); tbf_free(this); @@ -798,7 +799,7 @@ void gprs_rlcmac_tbf::handle_timeout() } /* Finish waiting after IMM.ASS confirm timer for CCCH assignment (see timer X2002) */ - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(this); dl_tbf->m_wait_confirm = 0; if (dl_tbf->state_is(TBF_ST_ASSIGN)) { @@ -817,7 +818,7 @@ void gprs_rlcmac_tbf::handle_timeout() * PDCH. */ /* keep to flags */ - dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; + dl_tbf->state_fsm.state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; dl_tbf->update(); @@ -831,15 +832,15 @@ std::string gprs_rlcmac_tbf::rlcmac_diag() { std::ostringstream os; os << "|"; - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) os << "Assignment was on CCCH|"; - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) os << "Assignment was on PACCH|"; - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_UL_DATA))) + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_UL_DATA))) os << "Uplink data was received|"; else if (direction == GPRS_RLCMAC_UL_TBF) os << "No uplink data received yet|"; - if ((state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) + if ((state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) os << "Downlink ACK was received|"; else if (direction == GPRS_RLCMAC_DL_TBF) os << "No downlink ACK received yet|"; @@ -162,9 +162,6 @@ enum tbf_counters { /* TBF counters from 3GPP TS 44.060 ยง13.4 */ #define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0) #define TBF_SET_ASS_STATE_UL(t, st) do { t->set_ass_state_ul(st, __FILE__, __LINE__); } while(0) #define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0) -#define TBF_SET_ASS_ON(t, fl, chk) do { t->set_assigned_on(fl, chk, __FILE__, __LINE__); } while(0) -#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0) -#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0) #ifdef __cplusplus extern "C" { @@ -214,8 +211,6 @@ struct gprs_rlcmac_tbf { void poll_sched_set(const char *file, int line); void poll_sched_unset(const char *file, int line); bool check_n_clear(uint8_t state_flag); - void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line); - void ass_type_mod(uint8_t t, bool unset, const char *file, int line); const char *state_name() const; const char *name() const; @@ -276,7 +271,6 @@ struct gprs_rlcmac_tbf { /* attempt to make things a bit more fair */ void rotate_in_list(); - uint32_t state_flags; enum gprs_rlcmac_tbf_direction direction; struct gprs_rlcmac_trx *trx; uint8_t first_ts; /* first TS used by TBF */ @@ -370,63 +364,6 @@ inline const char *gprs_rlcmac_tbf::state_name() const return osmo_fsm_inst_state_name(state_fsm.fi); } -/* Set assignment state and corrsponding flags */ -inline void gprs_rlcmac_tbf::set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line) -{ - tbf_fsm_state_chg(state_fsm.fi, TBF_ST_ASSIGN); - if (check_ccch) { - if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) - ass_type_mod(state_flag, false, file, line); - } else - state_flags |= (1 << state_flag); -} - -inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line) -{ - const char *ch = "UNKNOWN"; - switch (t) { - case GPRS_RLCMAC_FLAG_CCCH: - if (unset) { - if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) - return; - } else { - if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)) - LOGPSRC(DTBF, LOGL_ERROR, file, line, - "%s attempted to set ass. type CCCH which is already set.\n", - tbf_name(this)); - } - ch = "CCCH"; - break; - case GPRS_RLCMAC_FLAG_PACCH: - if (unset) { - if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) - return; - } else { - if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)) - LOGPSRC(DTBF, LOGL_ERROR, file, line, - "%s attempted to set ass. type PACCH which is already set.\n", - tbf_name(this)); - } - ch = "PACCH"; - break; - default: - LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n", - tbf_name(this), unset ? "un" : "", t); - return; - } - - LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n", - tbf_name(this), unset ? "un" : "", ch, - state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH), - state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)); - - if (unset) { - state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */ - state_flags &= ~(1 << t); - } else - state_flags |= (1 << t); -} - inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line) { LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n", @@ -456,8 +393,8 @@ inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag) { - if ((state_flags & (1 << state_flag))) { - state_flags &= ~(1 << state_flag); + if ((state_fsm.state_flags & (1 << state_flag))) { + state_fsm.state_flags &= ~(1 << state_flag); return true; } @@ -481,7 +418,7 @@ inline bool gprs_rlcmac_tbf::is_tfi_assigned() const return state_fsm.fi->state > TBF_ST_ASSIGN || (direction == GPRS_RLCMAC_DL_TBF && state_fsm.fi->state == TBF_ST_ASSIGN && - (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))); + (state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))); } inline uint8_t gprs_rlcmac_tbf::tfi() const diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index eb215fe4..12fd99fa 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -605,7 +605,7 @@ void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf) old_tbf->was_releasing = old_tbf->state_is(TBF_ST_WAIT_RELEASE); /* change state */ - TBF_SET_ASS_ON(this, GPRS_RLCMAC_FLAG_PACCH, true); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_ASSIGN_ADD_PACCH, NULL); /* Start timer, expiry in gprs_rlcmac_tbf::handle_timeout tbf_free()s the TBF */ T_START(this, T0, -2001, "assignment (PACCH)", true); @@ -615,7 +615,7 @@ void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf) was_releasing = state_is(TBF_ST_WAIT_RELEASE); /* change state */ - TBF_SET_ASS_ON(this, GPRS_RLCMAC_FLAG_CCCH, false); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_ASSIGN_ADD_CCCH, NULL); /* send immediate assignment */ if ((pgroup = imsi2paging_group(imsi())) > 999) @@ -777,7 +777,7 @@ bool gprs_rlcmac_dl_tbf::handle_ack_nack() { bool ack_recovered = false; - state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK); + state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK); if (check_n_clear(GPRS_RLCMAC_FLAG_TO_DL_ACK)) { ack_recovered = true; } @@ -957,7 +957,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( if (m_last_dl_poll_fn < 0) m_last_dl_poll_fn = fn; - need_poll = state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); + need_poll = state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx. */ @@ -985,7 +985,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( if (is_final) T_START(this, T3191, 3191, "final block (DL-TBF)", true); - state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); /* clear poll timeout flag */ + state_fsm.state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); /* clear poll timeout flag */ /* Clear request flag */ m_dl_ack_requested = false; @@ -1251,7 +1251,7 @@ int gprs_rlcmac_dl_tbf::release() m_wait_confirm = 0; m_window.reset(); - TBF_ASS_TYPE_UNSET(this, GPRS_RLCMAC_FLAG_CCCH); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_ASSIGN_DEL_CCCH, NULL); return 0; } @@ -1277,7 +1277,7 @@ int gprs_rlcmac_dl_tbf::abort() /* reset rlc states */ m_window.reset(); - TBF_ASS_TYPE_UNSET(this, GPRS_RLCMAC_FLAG_CCCH); + osmo_fsm_inst_dispatch(this->state_fsm.fi, TBF_EV_ASSIGN_DEL_CCCH, NULL); return 0; } @@ -1324,7 +1324,7 @@ void gprs_rlcmac_dl_tbf::request_dl_ack() bool gprs_rlcmac_dl_tbf::need_control_ts() const { - return state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK) || + return state_fsm.state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK) || m_tx_counter >= POLL_ACK_AFTER_FRAMES || m_dl_ack_requested; } diff --git a/src/tbf_fsm.c b/src/tbf_fsm.c index 3bf701a4..93019313 100644 --- a/src/tbf_fsm.c +++ b/src/tbf_fsm.c @@ -41,10 +41,85 @@ const struct osmo_tdef_state_timeout tbf_fsm_timeouts[32] = { }; const struct value_string tbf_fsm_event_names[] = { - { TBF_EV_FOOBAR, "FOOBAR" }, + { TBF_EV_ASSIGN_ADD_CCCH, "ASSIGN_ADD_CCCH" }, + { TBF_EV_ASSIGN_ADD_PACCH, "ASSIGN_ADD_PACCH" }, + { TBF_EV_ASSIGN_DEL_CCCH, "ASSIGN_DEL_CCCH" }, { 0, NULL } }; +static void mod_ass_type(struct tbf_fsm_ctx *ctx, uint8_t t, bool set) +{ + const char *ch = "UNKNOWN"; + bool prev_set = ctx->state_flags & (1 << t); + + switch (t) { + case GPRS_RLCMAC_FLAG_CCCH: + ch = "CCCH"; + break; + case GPRS_RLCMAC_FLAG_PACCH: + ch = "PACCH"; + break; + default: + LOGPTBF(ctx->tbf, LOGL_ERROR, + "attempted to %sset unexpected ass. type %d - FIXME!\n", + set ? "" : "un", t); + return; + } + + if (set && prev_set) { + LOGPTBF(ctx->tbf, LOGL_ERROR, + "attempted to set ass. type %s which is already set.\n", ch); + } else if (!set && !prev_set) { + return; + } + + LOGPTBF(ctx->tbf, LOGL_INFO, "%sset ass. type %s [prev CCCH:%u, PACCH:%u]\n", + set ? "" : "un", ch, + !!(ctx->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)), + !!(ctx->state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))); + + if (set) { + ctx->state_flags |= (1 << t); + } else { + ctx->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */ + ctx->state_flags &= ~(1 << t); + } +} + + +static void st_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct tbf_fsm_ctx *ctx = (struct tbf_fsm_ctx *)fi->priv; + switch (event) { + case TBF_EV_ASSIGN_ADD_CCCH: + mod_ass_type(ctx, GPRS_RLCMAC_FLAG_CCCH, true); + tbf_fsm_state_chg(fi, tbf_direction(ctx->tbf) == GPRS_RLCMAC_DL_TBF ? + TBF_ST_ASSIGN : TBF_ST_FLOW); + break; + case TBF_EV_ASSIGN_ADD_PACCH: + mod_ass_type(ctx, GPRS_RLCMAC_FLAG_PACCH, true); + tbf_fsm_state_chg(fi, TBF_ST_ASSIGN); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_assign(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct tbf_fsm_ctx *ctx = (struct tbf_fsm_ctx *)fi->priv; + switch (event) { + case TBF_EV_ASSIGN_ADD_CCCH: + mod_ass_type(ctx, GPRS_RLCMAC_FLAG_CCCH, true); + break; + case TBF_EV_ASSIGN_ADD_PACCH: + mod_ass_type(ctx, GPRS_RLCMAC_FLAG_PACCH, true); + break; + default: + OSMO_ASSERT(0); + } +} + static void tbf_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) { /* TODO: needed ? @@ -64,24 +139,25 @@ static int tbf_fsm_timer_cb(struct osmo_fsm_inst *fi) static struct osmo_fsm_state tbf_fsm_states[] = { [TBF_ST_NULL] = { .in_event_mask = - 0, + X(TBF_EV_ASSIGN_ADD_CCCH) | + X(TBF_EV_ASSIGN_ADD_PACCH), .out_state_mask = X(TBF_ST_ASSIGN) | X(TBF_ST_FLOW) | X(TBF_ST_RELEASING), .name = "NULL", - //.action = st_null, + .action = st_null, }, [TBF_ST_ASSIGN] = { .in_event_mask = - 0, + X(TBF_EV_ASSIGN_ADD_CCCH) | + X(TBF_EV_ASSIGN_ADD_PACCH), .out_state_mask = X(TBF_ST_FLOW) | X(TBF_ST_FINISHED) | X(TBF_ST_RELEASING), .name = "ASSIGN", - //.onenter = st_assign_on_enter, - //.action = st_assign, + .action = st_assign, }, [TBF_ST_FLOW] = { .in_event_mask = @@ -91,8 +167,6 @@ static struct osmo_fsm_state tbf_fsm_states[] = { X(TBF_ST_WAIT_RELEASE) | X(TBF_ST_RELEASING), .name = "FLOW", - //.onenter = st_flow_on_enter, - //.action = st_flow, }, [TBF_ST_FINISHED] = { .in_event_mask = @@ -100,8 +174,6 @@ static struct osmo_fsm_state tbf_fsm_states[] = { .out_state_mask = X(TBF_ST_WAIT_RELEASE), .name = "FINISHED", - //.onenter = st_finished_on_enter, - //.action = st_finished, }, [TBF_ST_WAIT_RELEASE] = { .in_event_mask = @@ -109,7 +181,6 @@ static struct osmo_fsm_state tbf_fsm_states[] = { .out_state_mask = X(TBF_ST_RELEASING), .name = "WAIT_RELEASE", - //.action = st_wait_release, }, [TBF_ST_RELEASING] = { .in_event_mask = @@ -117,10 +188,21 @@ static struct osmo_fsm_state tbf_fsm_states[] = { .out_state_mask = 0, .name = "RELEASING", - //.action = st_releasing, }, }; +void tbf_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct tbf_fsm_ctx *ctx = (struct tbf_fsm_ctx *)fi->priv; + switch (event) { + case TBF_EV_ASSIGN_DEL_CCCH: + mod_ass_type(ctx, GPRS_RLCMAC_FLAG_CCCH, false); + break; + default: + OSMO_ASSERT(0); + } +} + struct osmo_fsm tbf_fsm = { .name = "TBF", .states = tbf_fsm_states, @@ -129,6 +211,8 @@ struct osmo_fsm tbf_fsm = { .cleanup = tbf_fsm_cleanup, .log_subsys = DTBF, .event_names = tbf_fsm_event_names, + .allstate_action = tbf_fsm_allstate_action, + .allstate_event_mask = X(TBF_EV_ASSIGN_DEL_CCCH), }; static __attribute__((constructor)) void tbf_fsm_init(void) diff --git a/src/tbf_fsm.h b/src/tbf_fsm.h index 84bb4373..ed025ca5 100644 --- a/src/tbf_fsm.h +++ b/src/tbf_fsm.h @@ -27,7 +27,9 @@ struct gprs_rlcmac_tbf; enum tbf_fsm_event { - TBF_EV_FOOBAR, + TBF_EV_ASSIGN_ADD_CCCH, /* An assignment is sent over CCCH and confirmation from MS is pending */ + TBF_EV_ASSIGN_ADD_PACCH, /* An assignment is sent over PACCH and confirmation from MS is pending */ + TBF_EV_ASSIGN_DEL_CCCH, /* An assignment previously sent over CCCH has been confirmed by MS */ }; enum tbf_fsm_states { @@ -42,6 +44,7 @@ enum tbf_fsm_states { struct tbf_fsm_ctx { struct osmo_fsm_inst *fi; struct gprs_rlcmac_tbf* tbf; /* back pointer */ + uint32_t state_flags; }; extern const struct osmo_tdef_state_timeout tbf_fsm_timeouts[32]; diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 5ca02d95..2874fc63 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -154,7 +154,7 @@ gprs_rlcmac_ul_tbf *tbf_alloc_ul_pacch(struct gprs_rlcmac_bts *bts, GprsMs *ms, return NULL; } tbf->m_contention_resolution_done = 1; - TBF_SET_ASS_ON(tbf, GPRS_RLCMAC_FLAG_PACCH, false); + osmo_fsm_inst_dispatch(tbf->state_fsm.fi, TBF_EV_ASSIGN_ADD_PACCH, NULL); tbf->update_ms(tlli, GPRS_RLCMAC_UL_TBF); OSMO_ASSERT(tbf->ms()); @@ -172,8 +172,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_ccch(struct gprs_rlcmac_bts *bts, struct /* Caller will most probably send a Imm Ass Reject after return */ return NULL; } - TBF_SET_STATE(tbf, TBF_ST_FLOW); - TBF_ASS_TYPE_SET(tbf, GPRS_RLCMAC_FLAG_CCCH); + osmo_fsm_inst_dispatch(tbf->state_fsm.fi, TBF_EV_ASSIGN_ADD_CCCH, NULL); tbf->contention_resolution_start(); OSMO_ASSERT(tbf->ms()); @@ -215,7 +214,7 @@ struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts, ms_attach_tbf(ms, ul_tbf); llist_add(tbf_trx_list((struct gprs_rlcmac_tbf *)ul_tbf), &trx->ul_tbfs); bts_do_rate_ctr_inc(ul_tbf->bts, CTR_TBF_UL_ALLOCATED); - TBF_SET_ASS_ON(ul_tbf, GPRS_RLCMAC_FLAG_PACCH, false); + osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, TBF_EV_ASSIGN_ADD_PACCH, NULL); TBF_SET_ASS_STATE_UL(ul_tbf, GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ); return ul_tbf; @@ -287,7 +286,7 @@ bool gprs_rlcmac_ul_tbf::ctrl_ack_to_toggle() if (check_n_clear(GPRS_RLCMAC_FLAG_TO_UL_ACK)) return true; /* GPRS_RLCMAC_FLAG_TO_UL_ACK was set, now cleared */ - state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK); + state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK); return false; /* GPRS_RLCMAC_FLAG_TO_UL_ACK was unset, now set */ } @@ -398,7 +397,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged( const uint16_t ws = m_window.ws(); - this->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA); + this->state_fsm.state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA); LOGPTBFUL(this, LOGL_DEBUG, "UL DATA TFI=%d received (V(Q)=%d .. " "V(R)=%d)\n", rlc->tfi, this->m_window.v_q(), |