tbf: Move existing tbf_state implementation to osmo_fsm

This is only an initial implementation, where all state changes are
still done outside the FSM itself.
The idea is to do the move in several commits so that they can be
digested better in logical steps and avoid major break up.

Related: OS#2709
Change-Id: I6bb4baea2dee191ba5bbcbec2ea9dcf681aa1237
This commit is contained in:
Pau Espin 2021-05-14 12:50:46 +02:00
parent 38f80be73b
commit dc2aaac29f
17 changed files with 125013 additions and 364 deletions

View File

@ -14,16 +14,16 @@ Notes:
Queue of next frames to be transmitted.
States:
GPRS_RLCMAC_ASSIGN
TBF_ST_ASSIGN
After a downlink TBF is created, it resides in this state until the
block flow can start. This is required to give the mobile time to listen
to connect to downlink PDCH.
GPRS_RLCMAC_FLOW,
TBF_ST_FLOW,
During packet flow, this state indicates downlink and uplink TBF block
flow.
GPRS_RLCMAC_FINISHED,
TBF_ST_FINISHED,
Uplink TBF:
After final block is received AND all other blocks are completely
received, the state is entered. The PACKET CONTROL ACK is still not
@ -33,11 +33,11 @@ States:
downlink blocks are acknowledged yet. (Counter N3015 is counted on each
poll request.)
GPRS_RLCMAC_WAIT_RELEASE,
TBF_ST_WAIT_RELEASE,
The all blocks on downlink TBF have been acked by mobile. The penalty
timer T3192 is running on mobile.
GPRS_RLCMAC_RELEASING,
TBF_ST_RELEASING,
Wait for TFI/USF to be re-used. This state is entered when a counter
reaches it's maximum and T3169 is running.

View File

@ -58,6 +58,7 @@ libgprs_la_SOURCES = \
nacc_fsm.c \
neigh_cache.c \
tbf.cpp \
tbf_fsm.c \
tbf_ul.cpp \
tbf_dl.cpp \
bts.cpp \
@ -96,6 +97,7 @@ noinst_HEADERS = \
nacc_fsm.h \
neigh_cache.h \
tbf.h \
tbf_fsm.h \
tbf_ul.h \
tbf_dl.h \
bts.h \

View File

@ -159,7 +159,7 @@ static inline struct gprs_llc_queue *ms_llc_queue(struct GprsMs *ms)
static inline bool ms_need_dl_tbf(struct GprsMs *ms)
{
if (ms_dl_tbf(ms) != NULL &&
tbf_state((const struct gprs_rlcmac_tbf *)ms_dl_tbf(ms)) != GPRS_RLCMAC_WAIT_RELEASE)
tbf_state((const struct gprs_rlcmac_tbf *)ms_dl_tbf(ms)) != TBF_ST_WAIT_RELEASE)
return false;
return llc_queue_size(ms_llc_queue(ms)) > 0;

View File

@ -100,7 +100,7 @@ static struct gprs_rlcmac_ul_tbf *sched_select_uplink(struct gprs_rlcmac_pdch *p
/* we don't need to give resources in FINISHED state,
* because we have received all blocks and only poll
* for packet control ack. */
if (tbf->state_is_not(GPRS_RLCMAC_FLOW))
if (tbf->state_is_not(TBF_ST_FLOW))
continue;
if (require_gprs_only && tbf->is_egprs_enabled())
@ -247,7 +247,7 @@ static inline enum tbf_dl_prio tbf_compute_priority(const struct gprs_rlcmac_bts
if (tbf->is_control_ts(ts) && age > age_thresh2 && age_thresh2 > 0)
return DL_PRIO_HIGH_AGE;
if ((tbf->state_is(GPRS_RLCMAC_FLOW) && tbf->have_data()) || w->resend_needed() >= 0)
if ((tbf->state_is(TBF_ST_FLOW) && tbf->have_data()) || w->resend_needed() >= 0)
return DL_PRIO_NEW_DATA;
if (tbf->is_control_ts(ts) && age > age_thresh1 && tbf->keep_open(fn))
@ -306,8 +306,8 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts, struct gp
if (tbf->direction != GPRS_RLCMAC_DL_TBF)
continue;
/* no DL resources needed, go next */
if (tbf->state_is_not(GPRS_RLCMAC_FLOW)
&& tbf->state_is_not(GPRS_RLCMAC_FINISHED))
if (tbf->state_is_not(TBF_ST_FLOW)
&& tbf->state_is_not(TBF_ST_FINISHED))
continue;
/* waiting for CCCH IMM.ASS confirm */

View File

@ -358,7 +358,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
if (tbf->state_is(TBF_ST_WAIT_RELEASE) &&
tbf->direction == new_tbf->direction)
tbf_free(tbf);
@ -369,7 +369,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"changed type from CCCH to PACCH\n");
TBF_ASS_TYPE_SET(new_tbf, GPRS_RLCMAC_FLAG_PACCH);
}
TBF_SET_STATE(new_tbf, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(new_tbf, TBF_ST_FLOW);
/* stop pending assignment timer */
new_tbf->t_stop(T0, "control acked (DL-TBF)");
if (new_tbf->check_n_clear(GPRS_RLCMAC_FLAG_TO_DL_ASS))
@ -390,11 +390,11 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
if (tbf->state_is(TBF_ST_WAIT_RELEASE) &&
tbf->direction == new_tbf->direction)
tbf_free(tbf);
TBF_SET_STATE(new_tbf, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(new_tbf, TBF_ST_FLOW);
if (new_tbf->check_n_clear(GPRS_RLCMAC_FLAG_TO_UL_ASS))
LOGPTBF(new_tbf, LOGL_NOTICE, "Recovered uplink assignment for UL\n");
@ -677,7 +677,7 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request,
/* Get rid of previous finished UL TBF before providing a new one */
if (ul_tbf) {
if (!ul_tbf->state_is(GPRS_RLCMAC_FINISHED))
if (!ul_tbf->state_is(TBF_ST_FINISHED))
LOGPTBFUL(ul_tbf, LOGL_NOTICE,
"Got PACKET RESOURCE REQ while TBF not finished, killing pending UL TBF\n");
tbf_free(ul_tbf);

View File

@ -134,7 +134,6 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_
m_tfi(0),
m_created_ts(0),
m_ctrs(NULL),
state(GPRS_RLCMAC_NULL),
m_ms(ms),
dl_ass_state(GPRS_RLCMAC_DL_ASS_NONE),
ul_ass_state(GPRS_RLCMAC_UL_ASS_NONE),
@ -153,12 +152,22 @@ 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;
state_fsm.tbf = this;
state_fsm.fi = osmo_fsm_inst_alloc(&tbf_fsm, this, &state_fsm, LOGL_INFO, NULL);
m_rlc.init();
m_llc.init();
m_name_buf[0] = '\0';
}
gprs_rlcmac_tbf::~gprs_rlcmac_tbf()
{
osmo_fsm_inst_free(state_fsm.fi);
state_fsm.fi = NULL;
}
uint32_t gprs_rlcmac_tbf::tlli() const
{
return m_ms ? ms_tlli(m_ms) : GSM_RESERVED_TMSI;
@ -264,7 +273,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(tbf);
bts_do_rate_ctr_inc(tbf->bts, CTR_TBF_UL_FREED);
if (tbf->state_is(GPRS_RLCMAC_FLOW))
if (tbf->state_is(TBF_ST_FLOW))
bts_do_rate_ctr_inc(tbf->bts, CTR_TBF_UL_ABORTED);
rate_ctr_group_free(ul_tbf->m_ul_egprs_ctrs);
rate_ctr_group_free(ul_tbf->m_ul_gprs_ctrs);
@ -276,7 +285,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
rate_ctr_group_free(dl_tbf->m_dl_gprs_ctrs);
}
bts_do_rate_ctr_inc(tbf->bts, CTR_TBF_DL_FREED);
if (tbf->state_is(GPRS_RLCMAC_FLOW))
if (tbf->state_is(TBF_ST_FLOW))
bts_do_rate_ctr_inc(tbf->bts, CTR_TBF_DL_ABORTED);
}
@ -353,15 +362,6 @@ int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
return 0;
}
const char *gprs_rlcmac_tbf::tbf_state_name[] = {
"NULL",
"ASSIGN",
"FLOW",
"FINISHED",
"WAIT RELEASE",
"RELEASING",
};
void gprs_rlcmac_tbf::n_reset(enum tbf_counters n)
{
if (n >= N_MAX) {
@ -636,10 +636,10 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_
}
bts_do_rate_ctr_inc(bts, CTR_RLC_ACK_TIMEDOUT);
bts_do_rate_ctr_inc(bts, CTR_PUAN_POLL_TIMEDOUT);
if (state_is(GPRS_RLCMAC_FINISHED)) {
if (state_is(TBF_ST_FINISHED)) {
if (ul_tbf->n_inc(N3103)) {
bts_do_rate_ctr_inc(bts, CTR_PUAN_POLL_FAILED);
TBF_SET_STATE(ul_tbf, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(ul_tbf, TBF_ST_RELEASING);
T_START(ul_tbf, T3169, 3169, "MAX N3103 reached", false);
return;
}
@ -658,7 +658,7 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_
bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_TIMEDOUT);
bts_do_rate_ctr_inc(bts, CTR_PUA_POLL_TIMEDOUT);
if (n_inc(N3105)) {
TBF_SET_STATE(this, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(this, TBF_ST_RELEASING);
T_START(this, T3195, 3195, "MAX N3105 reached", true);
bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_FAILED);
bts_do_rate_ctr_inc(bts, CTR_PUA_POLL_FAILED);
@ -677,7 +677,7 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_
bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_TIMEDOUT);
bts_do_rate_ctr_inc(bts, CTR_PDA_POLL_TIMEDOUT);
if (n_inc(N3105)) {
TBF_SET_STATE(this, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(this, TBF_ST_RELEASING);
T_START(this, T3195, 3195, "MAX N3105 reached", true);
bts_do_rate_ctr_inc(bts, CTR_RLC_ASS_FAILED);
bts_do_rate_ctr_inc(bts, CTR_PDA_POLL_FAILED);
@ -700,7 +700,7 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_
dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
}
if (dl_tbf->state_is(GPRS_RLCMAC_RELEASING))
if (dl_tbf->state_is(TBF_ST_RELEASING))
bts_do_rate_ctr_inc(bts, CTR_RLC_REL_TIMEDOUT);
else {
bts_do_rate_ctr_inc(bts, CTR_RLC_ACK_TIMEDOUT);
@ -708,7 +708,7 @@ void gprs_rlcmac_tbf::poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_
}
if (dl_tbf->n_inc(N3105)) {
TBF_SET_STATE(dl_tbf, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(dl_tbf, TBF_ST_RELEASING);
T_START(dl_tbf, T3195, 3195, "MAX N3105 reached", true);
bts_do_rate_ctr_inc(bts, CTR_PDAN_POLL_FAILED);
bts_do_rate_ctr_inc(bts, CTR_RLC_ACK_FAILED);
@ -768,6 +768,8 @@ int gprs_rlcmac_tbf::setup(int8_t use_trx, bool single_slot)
return -1;
}
tbf_update_state_fsm_name(this);
ms_attach_tbf(m_ms, this);
return 0;
@ -787,7 +789,7 @@ void gprs_rlcmac_tbf::handle_timeout()
/* PACCH assignment timeout (see timers X2000, X2001) */
if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) {
if (state_is(GPRS_RLCMAC_ASSIGN)) {
if (state_is(TBF_ST_ASSIGN)) {
LOGPTBF(this, LOGL_NOTICE, "releasing due to PACCH assignment timeout.\n");
tbf_free(this);
return;
@ -799,13 +801,13 @@ void gprs_rlcmac_tbf::handle_timeout()
if ((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(GPRS_RLCMAC_ASSIGN)) {
if (dl_tbf->state_is(TBF_ST_ASSIGN)) {
tbf_assign_control_ts(dl_tbf);
if (!dl_tbf->upgrade_to_multislot) {
/* change state to FLOW, so scheduler
* will start transmission */
TBF_SET_STATE(dl_tbf, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(dl_tbf, TBF_ST_FLOW);
return;
}
@ -940,7 +942,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
set_polling(new_poll_fn, ts, PDCH_ULC_POLL_DL_ASS);
} else {
dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
TBF_SET_STATE(new_dl_tbf, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(new_dl_tbf, TBF_ST_FLOW);
tbf_assign_control_ts(new_dl_tbf);
/* stop pending assignment timer */
new_dl_tbf->t_stop(T0, "assignment (DL-TBF)");
@ -1090,6 +1092,13 @@ const char *gprs_rlcmac_tbf::name() const
return m_name_buf;
}
void tbf_update_state_fsm_name(struct gprs_rlcmac_tbf *tbf)
{
osmo_fsm_inst_update_id_f_sanitize(tbf->state_fsm.fi, '_', "%s-TFI_%d",
tbf_direction(tbf) == GPRS_RLCMAC_UL_TBF ? "UL" : "DL",
tbf_tfi(tbf));
}
void gprs_rlcmac_tbf::rotate_in_list()
{
llist_del(tbf_trx_list((struct gprs_rlcmac_tbf *)this));
@ -1146,9 +1155,9 @@ bool gprs_rlcmac_tbf::is_control_ts(uint8_t ts) const
}
/* C API */
enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf)
enum tbf_fsm_states tbf_state(const struct gprs_rlcmac_tbf *tbf)
{
return tbf->state;
return (enum tbf_fsm_states)tbf->state_fsm.fi->state;
}
enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf)

View File

@ -47,6 +47,7 @@ extern "C" {
#include "coding_scheme.h"
#include <pdch_ul_controller.h>
#include <tbf_fsm.h>
#ifdef __cplusplus
}
#endif
@ -55,15 +56,6 @@ extern "C" {
* TBF instance
*/
enum gprs_rlcmac_tbf_state {
GPRS_RLCMAC_NULL = 0, /* new created TBF */
GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
};
enum gprs_rlcmac_tbf_dl_ass_state {
GPRS_RLCMAC_DL_ASS_NONE = 0,
GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
@ -166,7 +158,7 @@ enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
#define TBF_SET_STATE(t, st) do { tbf_fsm_state_chg(t->state_fsm.fi, st); } while(0)
#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)
@ -179,7 +171,7 @@ extern "C" {
#endif
struct gprs_rlcmac_tbf;
const char *tbf_name(const struct gprs_rlcmac_tbf *tbf);
enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf);
enum tbf_fsm_states tbf_state(const struct gprs_rlcmac_tbf *tbf);
enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf);
void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, struct GprsMs *ms);
struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf);
@ -197,6 +189,7 @@ int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts, uint32_t *poll_fn, unsigned int *rrbp);
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason t);
void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_pdch *pdch, uint32_t poll_fn, enum pdch_ulc_tbf_poll_reason reason);
void tbf_update_state_fsm_name(struct gprs_rlcmac_tbf *tbf);
#ifdef __cplusplus
}
#endif
@ -205,17 +198,16 @@ void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_pdch *pdch
struct gprs_rlcmac_tbf {
gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);
virtual ~gprs_rlcmac_tbf() {}
virtual ~gprs_rlcmac_tbf();
virtual gprs_rlc_window *window() = 0;
int setup(int8_t use_trx, bool single_slot);
bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
bool state_is(enum tbf_fsm_states rhs) const;
bool state_is_not(enum tbf_fsm_states rhs) const;
bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
void set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line);
void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
@ -325,7 +317,7 @@ struct gprs_rlcmac_tbf {
time_t m_created_ts;
struct rate_ctr_group *m_ctrs;
enum gprs_rlcmac_tbf_state state;
struct tbf_fsm_ctx state_fsm;
struct llist_item m_ms_list;
struct llist_item m_trx_list;
@ -335,8 +327,6 @@ protected:
gprs_llc_queue *llc_queue();
const gprs_llc_queue *llc_queue() const;
static const char *tbf_state_name[6];
struct GprsMs *m_ms;
private:
void enable_egprs();
@ -349,9 +339,9 @@ private:
mutable char m_name_buf[60];
};
inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
inline bool gprs_rlcmac_tbf::state_is(enum tbf_fsm_states rhs) const
{
return state == rhs;
return tbf_state(this) == rhs;
}
inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
@ -369,20 +359,21 @@ inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state r
return ul_ack_state == rhs;
}
inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
inline bool gprs_rlcmac_tbf::state_is_not(enum tbf_fsm_states rhs) const
{
return state != rhs;
return tbf_state(this) != rhs;
}
inline const char *gprs_rlcmac_tbf::state_name() const
{
return tbf_state_name[state];
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)
{
set_state(GPRS_RLCMAC_ASSIGN, file, 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);
@ -436,14 +427,6 @@ inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *fil
state_flags |= (1 << t);
}
inline void gprs_rlcmac_tbf::set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line)
{
LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
tbf_name(this),
tbf_state_name[state], tbf_state_name[new_state]);
state = new_state;
}
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",
@ -495,9 +478,9 @@ inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
{
/* The TBF is established or has been assigned by a IMM.ASS for
* download */
return state > GPRS_RLCMAC_ASSIGN ||
return state_fsm.fi->state > TBF_ST_ASSIGN ||
(direction == GPRS_RLCMAC_DL_TBF &&
state == GPRS_RLCMAC_ASSIGN &&
state_fsm.fi->state == TBF_ST_ASSIGN &&
(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
}

View File

@ -98,7 +98,7 @@ static void llc_timer_cb(void *_tbf)
{
struct gprs_rlcmac_dl_tbf *tbf = (struct gprs_rlcmac_dl_tbf *)_tbf;
if (tbf->state_is_not(GPRS_RLCMAC_FLOW))
if (tbf->state_is_not(TBF_ST_FLOW))
return;
LOGPTBFDL(tbf, LOGL_DEBUG, "LLC receive timeout, requesting DL ACK\n");
@ -221,7 +221,7 @@ int gprs_rlcmac_dl_tbf::append_data(uint16_t pdu_delay_csec,
llc_queue()->enqueue(llc_msg, &expire_time);
start_llc_timer();
if (state_is(GPRS_RLCMAC_WAIT_RELEASE)) {
if (state_is(TBF_ST_WAIT_RELEASE)) {
LOGPTBFDL(this, LOGL_DEBUG, "in WAIT RELEASE state (T3193), so reuse TBF\n");
establish_dl_tbf_on_pacch();
}
@ -510,7 +510,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn,
/* re-send block with negative aknowlegement */
m_window.m_v_b.mark_unacked(bsn);
bts_do_rate_ctr_inc(bts, CTR_RLC_RESENT);
} else if (state_is(GPRS_RLCMAC_FINISHED)) {
} else if (state_is(TBF_ST_FINISHED)) {
/* If the TBF is in finished, we already sent all packages at least once.
* If any packages could have been sent (because of unacked) it should have
* been catched up by the upper if(bsn >= 0) */
@ -602,7 +602,7 @@ void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf)
if (old_tbf) {
LOGPTBFDL(this, LOGL_DEBUG, "Send dowlink assignment on PACCH, because %s exists\n", old_tbf->name());
TBF_SET_ASS_STATE_DL(old_tbf, GPRS_RLCMAC_DL_ASS_SEND_ASS);
old_tbf->was_releasing = old_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
old_tbf->was_releasing = old_tbf->state_is(TBF_ST_WAIT_RELEASE);
/* change state */
TBF_SET_ASS_ON(this, GPRS_RLCMAC_FLAG_PACCH, true);
@ -612,7 +612,7 @@ void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf)
} else {
LOGPTBFDL(this, LOGL_DEBUG, "Send dowlink assignment on PCH, no TBF exist (IMSI=%s)\n",
imsi());
was_releasing = state_is(GPRS_RLCMAC_WAIT_RELEASE);
was_releasing = state_is(TBF_ST_WAIT_RELEASE);
/* change state */
TBF_SET_ASS_ON(this, GPRS_RLCMAC_FLAG_CCCH, false);
@ -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, GPRS_RLCMAC_FINISHED);
TBF_SET_STATE(this, TBF_ST_FINISHED);
}
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, GPRS_RLCMAC_FINISHED);
TBF_SET_STATE(this, TBF_ST_FINISHED);
}
/* dequeue next LLC frame, if any */
@ -1211,7 +1211,7 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
"V(B): (V(A)=%d)\"%s\"(V(S)-1=%d) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid\n",
m_window.v_a(), show_v_b, m_window.v_s_mod(-1));
if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
if (state_is(TBF_ST_FINISHED) && m_window.window_empty()) {
LOGPTBFDL(this, LOGL_NOTICE,
"Received acknowledge of all blocks, but without final ack inidcation (don't worry)\n");
}
@ -1241,7 +1241,7 @@ int gprs_rlcmac_dl_tbf::release()
/* report all outstanding packets as received */
gprs_rlcmac_received_lost(this, received, 0);
TBF_SET_STATE(this, GPRS_RLCMAC_WAIT_RELEASE);
TBF_SET_STATE(this, TBF_ST_WAIT_RELEASE);
/* start T3193 */
T_START(this, T3193, 3193, "release (DL-TBF)", true);
@ -1260,7 +1260,7 @@ int gprs_rlcmac_dl_tbf::abort()
{
uint16_t lost;
if (state_is(GPRS_RLCMAC_FLOW)) {
if (state_is(TBF_ST_FLOW)) {
/* range V(A)..V(S)-1 */
lost = m_window.count_unacked();
@ -1272,7 +1272,7 @@ int gprs_rlcmac_dl_tbf::abort()
* (partly) encoded in chunk 1 of block V(A). (optional) */
}
TBF_SET_STATE(this, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(this, TBF_ST_RELEASING);
/* reset rlc states */
m_window.reset();
@ -1293,7 +1293,7 @@ int gprs_rlcmac_dl_tbf::rcvd_dl_ack(bool final_ack, unsigned first_bsn,
if (final_ack) {
LOGPTBFDL(this, LOGL_DEBUG, "Final ACK received.\n");
rc = maybe_start_new_window();
} else if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
} else if (state_is(TBF_ST_FINISHED) && m_window.window_empty()) {
LOGPTBFDL(this, LOGL_NOTICE,
"Received acknowledge of all blocks, but without final ack indication (don't worry)\n");
}

137
src/tbf_fsm.c Normal file
View File

@ -0,0 +1,137 @@
/* tbf_fsm.c
*
* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <unistd.h>
#include <talloc.h>
#include <tbf_fsm.h>
#include <gprs_rlcmac.h>
#include <gprs_debug.h>
#include <gprs_ms.h>
#include <encoding.h>
#include <bts.h>
#define X(s) (1 << (s))
const struct osmo_tdef_state_timeout tbf_fsm_timeouts[32] = {
[TBF_ST_NULL] = {},
[TBF_ST_ASSIGN] = { },
[TBF_ST_FLOW] = { },
[TBF_ST_FINISHED] = {},
[TBF_ST_WAIT_RELEASE] = {},
[TBF_ST_RELEASING] = {},
};
const struct value_string tbf_fsm_event_names[] = {
{ TBF_EV_FOOBAR, "FOOBAR" },
{ 0, NULL }
};
static void tbf_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
{
/* TODO: needed ?
* struct tbf_fsm_ctx *ctx = (struct tbf_fsm_ctx *)fi->priv;
*/
}
static int tbf_fsm_timer_cb(struct osmo_fsm_inst *fi)
{
switch (fi->T) {
default:
break;
}
return 0;
}
static struct osmo_fsm_state tbf_fsm_states[] = {
[TBF_ST_NULL] = {
.in_event_mask =
0,
.out_state_mask =
X(TBF_ST_ASSIGN) |
X(TBF_ST_FLOW) |
X(TBF_ST_RELEASING),
.name = "NULL",
//.action = st_null,
},
[TBF_ST_ASSIGN] = {
.in_event_mask =
0,
.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,
},
[TBF_ST_FLOW] = {
.in_event_mask =
0,
.out_state_mask =
X(TBF_ST_FINISHED) |
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 =
0,
.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 =
0,
.out_state_mask =
X(TBF_ST_RELEASING),
.name = "WAIT_RELEASE",
//.action = st_wait_release,
},
[TBF_ST_RELEASING] = {
.in_event_mask =
0,
.out_state_mask =
0,
.name = "RELEASING",
//.action = st_releasing,
},
};
struct osmo_fsm tbf_fsm = {
.name = "TBF",
.states = tbf_fsm_states,
.num_states = ARRAY_SIZE(tbf_fsm_states),
.timer_cb = tbf_fsm_timer_cb,
.cleanup = tbf_fsm_cleanup,
.log_subsys = DTBF,
.event_names = tbf_fsm_event_names,
};
static __attribute__((constructor)) void tbf_fsm_init(void)
{
OSMO_ASSERT(osmo_fsm_register(&tbf_fsm) == 0);
}

57
src/tbf_fsm.h Normal file
View File

@ -0,0 +1,57 @@
/* tbf_fsm.h
*
* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
#include <osmocom/core/fsm.h>
#include <osmocom/core/tdef.h>
#include <gprs_pcu.h>
struct gprs_rlcmac_tbf;
enum tbf_fsm_event {
TBF_EV_FOOBAR,
};
enum tbf_fsm_states {
TBF_ST_NULL = 0, /* new created TBF */
TBF_ST_ASSIGN, /* wait for downlink assignment */
TBF_ST_FLOW, /* RLC/MAC flow, resource needed */
TBF_ST_FINISHED, /* flow finished, wait for release */
TBF_ST_WAIT_RELEASE,/* wait for release or restart of DL TBF */
TBF_ST_RELEASING, /* releasing, wait to free TBI/USF */
};
struct tbf_fsm_ctx {
struct osmo_fsm_inst *fi;
struct gprs_rlcmac_tbf* tbf; /* back pointer */
};
extern const struct osmo_tdef_state_timeout tbf_fsm_timeouts[32];
/* Transition to a state, using the T timer defined in assignment_fsm_timeouts.
* The actual timeout value is in turn obtained from conn->T_defs.
* Assumes local variable fi exists. */
#define tbf_fsm_state_chg(fi, NEXT_STATE) \
osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, \
tbf_fsm_timeouts, \
the_pcu->T_defs, \
-1)
extern struct osmo_fsm tbf_fsm;

View File

@ -171,7 +171,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, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(tbf, TBF_ST_FLOW);
TBF_ASS_TYPE_SET(tbf, GPRS_RLCMAC_FLAG_CCCH);
tbf->contention_resolution_start();
OSMO_ASSERT(tbf->ms());
@ -334,7 +334,7 @@ void gprs_rlcmac_ul_tbf::contention_resolution_success()
struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn, uint8_t ts)
{
int final = (state_is(GPRS_RLCMAC_FINISHED));
int final = (state_is(TBF_ST_FINISHED));
struct msgb *msg;
int rc;
unsigned int rrbp = 0;
@ -527,7 +527,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
rdbi = &block->block_info;
/* Check if we already received all data TBF had to send: */
if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
if (this->state_is(TBF_ST_FLOW) /* still in flow state */
&& this->m_window.v_q() == this->m_window.v_r() /* if complete */
&& block->len) { /* if there was ever a last block received */
LOGPTBFUL(this, LOGL_DEBUG,
@ -535,7 +535,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, GPRS_RLCMAC_FINISHED);
TBF_SET_STATE(this, TBF_ST_FINISHED);
/* Reset N3103 counter. */
this->n_reset(N3103);
}
@ -567,10 +567,10 @@ void gprs_rlcmac_ul_tbf::maybe_schedule_uplink_acknack(
}
if (countdown_finished) {
require_ack = true;
if (state_is(GPRS_RLCMAC_FLOW))
if (state_is(TBF_ST_FLOW))
LOGPTBFUL(this, LOGL_DEBUG,
"Scheduling Ack/Nack, because some data is missing and last block has CV==0.\n");
else if (state_is(GPRS_RLCMAC_FINISHED))
else if (state_is(TBF_ST_FINISHED))
LOGPTBFUL(this, LOGL_DEBUG,
"Scheduling final Ack/Nack, because all data was received and last block has CV==0.\n");
}
@ -816,7 +816,7 @@ gprs_rlc_window *gprs_rlcmac_ul_tbf::window()
void gprs_rlcmac_ul_tbf::usf_timeout()
{
if (n_inc(N3101)) {
TBF_SET_STATE(this, GPRS_RLCMAC_RELEASING);
TBF_SET_STATE(this, TBF_ST_RELEASING);
T_START(this, T3169, 3169, "MAX N3101 reached", false);
return;
}

View File

@ -34,6 +34,7 @@ extern "C" {
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/fsm.h>
}
/* globals used by the code */
@ -816,6 +817,7 @@ int main(int argc, char **argv)
log_set_category_filter(osmo_stderr_target, DTBF, 1, LOGL_INFO);
if (getenv("LOGL_DEBUG"))
log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
osmo_fsm_log_addr(false);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,7 @@ extern "C" {
#include <osmocom/vty/vty.h>
#include <osmocom/gprs/protocol/gsm_04_60.h>
#include <osmocom/gsm/l1sap.h>
#include <osmocom/core/fsm.h>
}
#include <errno.h>
@ -75,9 +76,9 @@ static int bts_handle_rach(struct gprs_rlcmac_bts *bts, uint16_t ra, uint32_t Fn
static void check_tbf(gprs_rlcmac_tbf *tbf)
{
OSMO_ASSERT(tbf);
if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
if (tbf->state_is(TBF_ST_WAIT_RELEASE))
OSMO_ASSERT(tbf->timers_pending(T3191) || tbf->timers_pending(T3193));
if (tbf->state_is(GPRS_RLCMAC_RELEASING))
if (tbf->state_is(TBF_ST_RELEASING))
OSMO_ASSERT(tbf->timers_pending(T_MAX));
}
@ -204,7 +205,7 @@ static gprs_rlcmac_dl_tbf *create_dl_tbf(struct gprs_rlcmac_bts *bts, uint8_t ms
/* "Establish" the DL TBF */
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_SEND_ASS);
TBF_SET_STATE(dl_tbf, GPRS_RLCMAC_FLOW);
TBF_SET_STATE(dl_tbf, TBF_ST_FLOW);
dl_tbf->m_wait_confirm = 0;
check_tbf(dl_tbf);
@ -286,7 +287,7 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
} while (block_nr < 3);
OSMO_ASSERT(dl_tbf->have_data());
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Queue a final ACK */
memset(rbb, 0, sizeof(rbb));
@ -294,7 +295,7 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
dl_tbf->rcvd_dl_ack(true, 1, rbb);
/* Clean up and ensure tbfs are in the correct state */
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_WAIT_RELEASE));
new_tbf = ms_dl_tbf(ms);
check_tbf(new_tbf);
OSMO_ASSERT(new_tbf != dl_tbf);
@ -357,20 +358,20 @@ static void test_tbf_delayed_release()
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Schedule two LLC frames */
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
dl_tbf->append_data(1000, llc_data, sizeof(llc_data));
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Drain the queue */
while (dl_tbf->have_data())
/* Request to send one RLC/MAC block */
request_dl_rlc_block(dl_tbf, &fn);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* ACK all blocks */
memset(rbb, 0xff, sizeof(rbb));
@ -387,12 +388,12 @@ static void test_tbf_delayed_release()
fn += 52 * ((msecs_to_frames(dl_tbf_idle_msec + 100) + 51)/ 52);
request_dl_rlc_block(dl_tbf, &fn);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FINISHED));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FINISHED));
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
/* Clean up and ensure tbfs are in the correct state */
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_WAIT_RELEASE));
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
check_tbf(dl_tbf);
tbf_free(dl_tbf);
@ -2139,7 +2140,7 @@ static void test_tbf_dl_reuse()
transmit_dl_data(bts, tlli1, &fn);
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0);
OSMO_ASSERT(ms_dl_tbf(ms1));
OSMO_ASSERT(ms_dl_tbf(ms1)->state_is(GPRS_RLCMAC_FINISHED));
OSMO_ASSERT(ms_dl_tbf(ms1)->state_is(TBF_ST_FINISHED));
dl_tbf1 = ms_dl_tbf(ms1);
@ -2164,27 +2165,27 @@ static void test_tbf_dl_reuse()
send_ul_mac_block(bts, 0, dl_tbf1->control_ts, &ulreq, get_poll_fn(dl_tbf1, dl_tbf1->control_ts));
OSMO_ASSERT(dl_tbf1->state_is(GPRS_RLCMAC_WAIT_RELEASE));
OSMO_ASSERT(dl_tbf1->state_is(TBF_ST_WAIT_RELEASE));
request_dl_rlc_block(dl_tbf1, &fn);
ms2 = bts_ms_by_tlli(bts, tlli1, GSM_RESERVED_TMSI);
OSMO_ASSERT(ms2 == ms1);
OSMO_ASSERT(ms_dl_tbf(ms2));
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_ASSIGN));
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(TBF_ST_ASSIGN));
dl_tbf2 = ms_dl_tbf(ms2);
OSMO_ASSERT(dl_tbf1 != dl_tbf2);
send_control_ack(dl_tbf1);
OSMO_ASSERT(dl_tbf2->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf2->state_is(TBF_ST_FLOW));
/* Transmit all data */
transmit_dl_data(bts, tlli1, &fn);
OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms2)) == 0);
OSMO_ASSERT(ms_dl_tbf(ms2));
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_FINISHED));
OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(TBF_ST_FINISHED));
TALLOC_FREE(the_pcu);
fprintf(stderr, "=== end %s ===\n", __func__);
@ -2573,7 +2574,7 @@ static void test_tbf_epdan_out_of_rx_window(void)
prlcmvb->mark_unacked(1286);
prlcmvb->mark_unacked(1287);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
block = bitvec_alloc(23, tall_pcu_ctx);
@ -2699,12 +2700,12 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Schedule a small LLC frame */
dl_tbf->append_data(1000, test_data, 10);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Drain the queue */
while (dl_tbf->have_data()) {
@ -2716,7 +2717,7 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
/* Schedule a large LLC frame */
dl_tbf->append_data(1000, test_data, sizeof(test_data));
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Drain the queue */
while (dl_tbf->have_data()) {
@ -2725,12 +2726,12 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs)
}
send_empty_block(dl_tbf, dl_tbf->control_ts, fn);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
/* Clean up and ensure tbfs are in the correct state */
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_WAIT_RELEASE));
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
check_tbf(dl_tbf);
tbf_free(dl_tbf);
@ -2757,7 +2758,7 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
for (i = 0; i < sizeof(test_data); i++)
test_data[i] = i%256;
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
/* Schedule a LLC frame
* passing only 100 bytes, since it is enough to construct
@ -2766,7 +2767,7 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts,
*/
dl_tbf->append_data(1000, test_data, 100);
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_FLOW));
return dl_tbf;
@ -2779,7 +2780,7 @@ static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf)
RCV_ACK(true, dl_tbf, rbb); /* Receive a final ACK */
/* Clean up and ensure tbfs are in the correct state */
OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
OSMO_ASSERT(dl_tbf->state_is(TBF_ST_WAIT_RELEASE));
TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);
check_tbf(dl_tbf);
tbf_free(dl_tbf);
@ -3305,6 +3306,7 @@ int main(int argc, char **argv)
log_parse_category_mask(osmo_stderr_target, "DRLCMAC,1:DRLCMACDATA,3:DRLCMACDL,3:DRLCMACUL,3:"
"DRLCMACSCHED,1:DRLCMACMEAS,3:DNS,3:DLBSSGP,3:DPCU,5:"
"DL1IF,6:DTBF,1:DTBFUL,1:DTBFDL,1:DLGLOBAL,2:");
osmo_fsm_log_addr(false);
vty_init(&pcu_vty_info);
pcu_vty_init();

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ extern "C" {
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/fsm.h>
}
#define OSMO_ASSERT_STR_EQ(a, b) \
@ -932,6 +933,7 @@ int main(int argc, char **argv)
log_set_category_filter(osmo_stderr_target, DTBF, 1, LOGL_INFO);
log_set_category_filter(osmo_stderr_target, DTBFUL, 1, LOGL_INFO);
osmo_fsm_log_addr(false);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);

View File

@ -1,15 +1,19 @@
MS(TLLI=0xffffffff, IMSI=, TA=220, 1/0,) Allocating DL TBF
TBF{NULL}: Allocated
TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=NULL) Setting Control TS 2
TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=NULL) Allocated: trx = 0, ul_slots = 04, dl_slots = 04
MS(TLLI=0xffffffff, IMSI=, TA=220, 1/0,) Allocating UL TBF
TBF{NULL}: Allocated
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL) Setting Control TS 4
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL) Allocated: trx = 0, ul_slots = 10, dl_slots = 00
MS(TLLI=0xffffffff, IMSI=, TA=220, 1/1,) Allocating UL TBF
TBF{NULL}: Allocated
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) Setting Control TS 1
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) Allocated: trx = 0, ul_slots = 02, dl_slots = 00
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) setting EGPRS UL window size to 64, base(64) slots(1) ws_pdch(0)
############## test_egprs_ul_ack_nack
MS(TLLI=0xffffffff, IMSI=, TA=220, 1/1,) Allocating UL TBF
TBF{NULL}: Allocated
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) Setting Control TS 4
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) Allocated: trx = 0, ul_slots = 10, dl_slots = 00
TBF(TFI=0 TLLI=0xffffffff DIR=UL STATE=NULL EGPRS) setting EGPRS UL window size to 64, base(64) slots(1) ws_pdch(0)