diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/bts.cpp | 51 | ||||
-rw-r--r-- | src/bts.h | 16 | ||||
-rw-r--r-- | src/encoding.cpp | 20 | ||||
-rw-r--r-- | src/gprs_ms.c | 885 | ||||
-rw-r--r-- | src/gprs_ms.cpp | 900 | ||||
-rw-r--r-- | src/gprs_ms.h | 316 | ||||
-rw-r--r-- | src/gprs_ms_storage.cpp | 64 | ||||
-rw-r--r-- | src/gprs_ms_storage.h | 10 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 6 | ||||
-rw-r--r-- | src/gprs_rlcmac_ts_alloc.cpp | 32 | ||||
-rw-r--r-- | src/llc.cpp | 30 | ||||
-rw-r--r-- | src/llc.h | 80 | ||||
-rw-r--r-- | src/pcu_l1_if.cpp | 21 | ||||
-rw-r--r-- | src/pcu_l1_if.h | 89 | ||||
-rw-r--r-- | src/pcu_utils.h | 23 | ||||
-rw-r--r-- | src/pcu_vty_functions.cpp | 98 | ||||
-rw-r--r-- | src/pdch.cpp | 58 | ||||
-rw-r--r-- | src/tbf.cpp | 106 | ||||
-rw-r--r-- | src/tbf.h | 54 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 86 | ||||
-rw-r--r-- | src/tbf_dl.h | 18 | ||||
-rw-r--r-- | src/tbf_ul.cpp | 30 | ||||
-rw-r--r-- | src/tbf_ul.h | 30 | ||||
-rw-r--r-- | tests/alloc/AllocTest.cpp | 75 | ||||
-rw-r--r-- | tests/app_info/AppInfoTest.cpp | 4 | ||||
-rw-r--r-- | tests/app_info/AppInfoTest.err | 11 | ||||
-rw-r--r-- | tests/edge/EdgeTest.cpp | 7 | ||||
-rw-r--r-- | tests/llc/LlcTest.cpp | 80 | ||||
-rw-r--r-- | tests/ms/MsTest.cpp | 474 | ||||
-rw-r--r-- | tests/tbf/TbfTest.cpp | 155 | ||||
-rw-r--r-- | tests/types/TypesTest.cpp | 32 |
32 files changed, 1960 insertions, 1903 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ece372d6..386a1f64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,7 +47,7 @@ libgprs_la_SOURCES = \ gprs_rlcmac_sched.cpp \ gprs_rlcmac_meas.cpp \ gprs_rlcmac_ts_alloc.cpp \ - gprs_ms.cpp \ + gprs_ms.c \ gprs_ms_storage.cpp \ gsm_timer.cpp \ pcu_l1_if.cpp \ diff --git a/src/bts.cpp b/src/bts.cpp index b4f902ab..bd0a1d20 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -712,7 +712,7 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn) ms = ms_by_tlli(tlli); if (ms) - dl_tbf = ms->dl_tbf(); + dl_tbf = ms_dl_tbf(ms); if (!dl_tbf) { LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x " "does not exit\n", tlli); @@ -1140,9 +1140,9 @@ GprsMs *BTS::ms_alloc(uint8_t ms_class, uint8_t egprs_ms_class) GprsMs *ms; ms = ms_store().create_ms(); - ms->set_timeout(osmo_tdef_get(m_bts.T_defs_pcu, -2030, OSMO_TDEF_S, -1)); - ms->set_ms_class(ms_class); - ms->set_egprs_ms_class(egprs_ms_class); + ms_set_timeout(ms, osmo_tdef_get(m_bts.T_defs_pcu, -2030, OSMO_TDEF_S, -1)); + ms_set_ms_class(ms, ms_class); + ms_set_egprs_ms_class(ms, egprs_ms_class); return ms; } @@ -1206,22 +1206,22 @@ void bts_update_tbf_ta(const char *p, uint32_t fn, uint8_t trx_no, uint8_t ts, i } } -void gprs_rlcmac_trx::reserve_slots(enum gprs_rlcmac_tbf_direction dir, +void bts_trx_reserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots) { unsigned i; - for (i = 0; i < ARRAY_SIZE(pdch); i += 1) + for (i = 0; i < ARRAY_SIZE(trx->pdch); i += 1) if (slots & (1 << i)) - pdch[i].reserve(dir); + trx->pdch[i].reserve(dir); } -void gprs_rlcmac_trx::unreserve_slots(enum gprs_rlcmac_tbf_direction dir, +void bts_trx_unreserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots) { unsigned i; - for (i = 0; i < ARRAY_SIZE(pdch); i += 1) + for (i = 0; i < ARRAY_SIZE(trx->pdch); i += 1) if (slots & (1 << i)) - pdch[i].unreserve(dir); + trx->pdch[i].unreserve(dir); } void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul) @@ -1277,3 +1277,34 @@ void bts_set_max_mcs(struct gprs_rlcmac_bts *bts, uint8_t mcs_dl, uint8_t mcs_ul bts->bts->set_max_mcs_dl(mcs_dl); bts->bts->set_max_mcs_ul(mcs_ul); } + + +struct gprs_rlcmac_bts *bts_data(struct BTS *bts) +{ + return &bts->m_bts; +} + +struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi) +{ + return bts->ms_by_imsi(imsi); +} + +uint8_t bts_max_cs_dl(const struct BTS *bts) +{ + return bts->max_cs_dl(); +} + +uint8_t bts_max_cs_ul(const struct BTS *bts) +{ + return bts->max_cs_ul(); +} + +uint8_t bts_max_mcs_dl(const struct BTS *bts) +{ + return bts->max_mcs_dl(); +} + +uint8_t bts_max_mcs_ul(const struct BTS *bts) +{ + return bts->max_mcs_ul(); +} @@ -90,15 +90,14 @@ struct gprs_rlcmac_trx { struct BTS *bts; uint8_t trx_no; -#ifdef __cplusplus - void reserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots); - void unreserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots); -#endif }; #ifdef __cplusplus extern "C" { #endif +void bts_trx_reserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots); +void bts_trx_unreserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots); + void bts_update_tbf_ta(const char *p, uint32_t fn, uint8_t trx_no, uint8_t ts, int8_t ta, bool is_rach); #ifdef __cplusplus } @@ -372,10 +371,11 @@ public: LListHead<gprs_rlcmac_tbf>& ul_tbfs(); LListHead<gprs_rlcmac_tbf>& dl_tbfs(); + + struct gprs_rlcmac_bts m_bts; private: int m_cur_fn; int m_cur_blk_fn; - struct gprs_rlcmac_bts m_bts; uint8_t m_max_cs_dl, m_max_cs_ul; uint8_t m_max_mcs_dl, m_max_mcs_ul; PollController m_pollController; @@ -459,11 +459,17 @@ inline void BTS::stat_item_add(unsigned int stat_id, int inc) { extern "C" { #endif void bts_cleanup(); + struct gprs_rlcmac_bts *bts_data(struct BTS *bts); struct gprs_rlcmac_bts *bts_main_data(); struct rate_ctr_group *bts_main_data_stats(); struct osmo_stat_item_group *bts_main_data_stat_items(); void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul); void bts_set_max_mcs(struct gprs_rlcmac_bts *bts, uint8_t mcs_dl, uint8_t mcs_ul); + struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi); + uint8_t bts_max_cs_dl(const struct BTS *bts); + uint8_t bts_max_cs_ul(const struct BTS *bts); + uint8_t bts_max_mcs_dl(const struct BTS *bts); + uint8_t bts_max_mcs_ul(const struct BTS *bts); #ifdef __cplusplus } diff --git a/src/encoding.cpp b/src/encoding.cpp index a16962ad..e7b1fb41 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -1388,7 +1388,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_gprs( delimiter = data_block + *num_chunks; e_pointer = (*num_chunks ? delimiter - 1 : NULL); - chunk = llc->chunk_size(); + chunk = llc_chunk_size(llc); space = rdbi->data_len - *offset; /* if chunk will exceed block limit */ @@ -1402,7 +1402,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_gprs( *e_pointer |= 0x02; /* set previous M bit = 1 */ } /* fill only space */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; /* return data block as message */ @@ -1421,7 +1421,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_gprs( if (e_pointer) *e_pointer |= 0x01; /* fill space */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; *offset = rdbi->data_len; @@ -1454,7 +1454,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_gprs( rdbi->e = 0; /* 0: extensions present */ // no need to set e_pointer nor increase delimiter /* fill only space, which is 1 octet less than chunk */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; /* return data block as message */ @@ -1485,7 +1485,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_gprs( rdbi->e = 0; /* 0: extensions present */ (*num_chunks)++; /* copy (rest of) LLC frame to space and reset later */ - llc->consume(data, chunk); + llc_consume_data(llc, data, chunk); if (count_payload) *count_payload = chunk; data += chunk; @@ -1536,7 +1536,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_egprs( prev_li = (struct rlc_li_field_egprs *) (*num_chunks ? delimiter - 1 : NULL); - chunk = llc->chunk_size(); + chunk = llc_chunk_size(llc); space = rdbi->data_len - *offset; /* if chunk will exceed block limit */ @@ -1546,7 +1546,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_egprs( "only remaining space, and we are done\n", chunk, space); /* fill only space */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; /* return data block as message */ @@ -1562,7 +1562,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_egprs( "this is a final block, we don't add length " "header, and we are done\n", chunk, space); /* fill space */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; *offset = rdbi->data_len; @@ -1578,7 +1578,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_egprs( "to start with an empty chunk\n", chunk, space); /* fill space */ - llc->consume(data, space); + llc_consume_data(llc, data, space); if (count_payload) *count_payload = space; *offset = rdbi->data_len; @@ -1610,7 +1610,7 @@ static Encoding::AppendResult rlc_data_to_dl_append_egprs( prev_li = li; (*num_chunks)++; /* copy (rest of) LLC frame to space and reset later */ - llc->consume(data, chunk); + llc_consume_data(llc, data, chunk); if (count_payload) *count_payload = chunk; data += chunk; diff --git a/src/gprs_ms.c b/src/gprs_ms.c new file mode 100644 index 00000000..94f69cde --- /dev/null +++ b/src/gprs_ms.c @@ -0,0 +1,885 @@ +/* gprs_ms.c + * + * Copyright (C) 2015-2020 by Sysmocom s.f.m.c. GmbH + * Author: Jacob Erlbeck <jerlbeck@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 "gprs_ms.h" +#include "bts.h" +#include "tbf.h" +#include "tbf_ul.h" +#include "gprs_debug.h" +#include "gprs_codel.h" +#include "pcu_utils.h" + +#include <time.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/timer.h> +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/gsm48.h> +#include <osmocom/core/logging.h> +#include "coding_scheme.h" + +#define GPRS_CODEL_SLOW_INTERVAL_MS 4000 + +extern void *tall_pcu_ctx; + +static int64_t now_msec() +{ + struct timespec ts; + osmo_clock_gettime(CLOCK_MONOTONIC, &ts); + + return (int64_t)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000; +} + +void gprs_default_cb_ms_idle(struct GprsMs *ms) +{ + talloc_free(ms); +} + +void gprs_default_cb_ms_active(struct GprsMs *ms) +{ + /* do nothing */ +} + +static struct gpr_ms_callback gprs_default_cb = { + .ms_idle = gprs_default_cb_ms_idle, + .ms_active = gprs_default_cb_ms_active, +}; + +void ms_timeout(void *data) +{ + struct GprsMs *ms = (struct GprsMs *) data; + LOGP(DRLCMAC, LOGL_INFO, "Timeout for MS object, TLLI = 0x%08x\n", + ms_tlli(ms)); + + if (ms->timer.data) { + ms->timer.data = NULL; + ms_unref(ms); + } +} + +static int ms_talloc_destructor(struct GprsMs *ms); +struct GprsMs *ms_alloc(struct BTS *bts, uint32_t tlli) +{ + struct GprsMs *ms = talloc_zero(tall_pcu_ctx, struct GprsMs); + + talloc_set_destructor(ms, ms_talloc_destructor); + + ms->bts = bts; + ms->cb = gprs_default_cb; + ms->tlli = tlli; + ms->new_ul_tlli = GSM_RESERVED_TMSI; + ms->new_dl_tlli = GSM_RESERVED_TMSI; + ms->ta = GSM48_TA_INVALID; + ms->current_cs_ul = UNKNOWN; + ms->current_cs_dl = UNKNOWN; + ms->is_idle = true; + INIT_LLIST_HEAD(&ms->list); + INIT_LLIST_HEAD(&ms->old_tbfs); + + int codel_interval = LLC_CODEL_USE_DEFAULT; + + LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli); + + ms->imsi[0] = '\0'; + memset(&ms->timer, 0, sizeof(ms->timer)); + ms->timer.cb = ms_timeout; + llc_queue_init(&ms->llc_queue); + + ms_set_mode(ms, GPRS); + + if (ms->bts) + codel_interval = bts_data(ms->bts)->llc_codel_interval_msec; + + if (codel_interval) { + if (codel_interval == LLC_CODEL_USE_DEFAULT) + codel_interval = GPRS_CODEL_SLOW_INTERVAL_MS; + ms->codel_state = talloc(ms, struct gprs_codel); + gprs_codel_init(ms->codel_state); + gprs_codel_set_interval(ms->codel_state, codel_interval); + } + ms->last_cs_not_low = now_msec(); + ms->app_info_pending = false; + return ms; +} + +static int ms_talloc_destructor(struct GprsMs *ms) +{ + struct llist_item *pos, *tmp; + + LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", ms_tlli(ms)); + + ms_set_reserved_slots(ms, NULL, 0, 0); + + if (osmo_timer_pending(&ms->timer)) + osmo_timer_del(&ms->timer); + + if (ms->ul_tbf) { + tbf_set_ms((struct gprs_rlcmac_tbf *)ms->ul_tbf, NULL); + ms->ul_tbf = NULL; + } + + if (ms->dl_tbf) { + tbf_set_ms((struct gprs_rlcmac_tbf *)ms->dl_tbf, NULL); + ms->dl_tbf = NULL; + } + + llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) { + struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)pos->entry; + tbf_set_ms(tbf, NULL); + } + + llc_queue_clear(&ms->llc_queue, ms->bts); + return 0; +} + + +void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb) +{ + if (cb) + ms->cb = *cb; + else + ms->cb = gprs_default_cb; +} + +static void ms_update_status(struct GprsMs *ms) +{ + if (ms->ref > 0) + return; + + if (ms_is_idle(ms) && !ms->is_idle) { + ms->is_idle = true; + ms->cb.ms_idle(ms); + /* this can be deleted by now, do not access it */ + return; + } + + if (!ms_is_idle(ms) && ms->is_idle) { + ms->is_idle = false; + ms->cb.ms_active(ms); + } +} + +struct GprsMs *ms_ref(struct GprsMs *ms) +{ + ms->ref += 1; + return ms; +} + +void ms_unref(struct GprsMs *ms) +{ + OSMO_ASSERT(ms->ref >= 0); + ms->ref -= 1; + if (ms->ref == 0) + ms_update_status(ms); +} + +void ms_start_timer(struct GprsMs *ms) +{ + if (ms->delay == 0) + return; + + if (!ms->timer.data) + ms->timer.data = ms_ref(ms); + + osmo_timer_schedule(&ms->timer, ms->delay, 0); +} + +void ms_stop_timer(struct GprsMs *ms) +{ + if (!ms->timer.data) + return; + + osmo_timer_del(&ms->timer); + ms->timer.data = NULL; + ms_unref(ms); +} + +void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode) +{ + ms->mode = mode; + + if (!ms->bts) + return; + + switch (ms->mode) { + case GPRS: + if (!mcs_is_gprs(ms->current_cs_ul)) { + ms->current_cs_ul = mcs_get_gprs_by_num( + bts_data(ms->bts)->initial_cs_ul); + if (!mcs_is_valid(ms->current_cs_ul)) + ms->current_cs_ul = CS1; + } + if (!mcs_is_gprs(ms->current_cs_dl)) { + ms->current_cs_dl = mcs_get_gprs_by_num( + bts_data(ms->bts)->initial_cs_dl); + if (!mcs_is_valid(ms->current_cs_dl)) + ms->current_cs_dl = CS1; + } + break; + + case EGPRS_GMSK: + case EGPRS: + if (!mcs_is_edge(ms->current_cs_ul)) { + ms->current_cs_ul = mcs_get_egprs_by_num( + bts_data(ms->bts)->initial_mcs_ul); + if (!mcs_is_valid(ms->current_cs_ul)) + ms->current_cs_ul = MCS1; + } + if (!mcs_is_edge(ms->current_cs_dl)) { + ms->current_cs_dl = mcs_get_egprs_by_num( + bts_data(ms->bts)->initial_mcs_dl); + if (!mcs_is_valid(ms->current_cs_dl)) + ms->current_cs_dl = MCS1; + } + break; + } +} + +static void ms_attach_ul_tbf(struct GprsMs *ms, struct gprs_rlcmac_ul_tbf *tbf) +{ + if (ms->ul_tbf == tbf) + return; + + LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", + ms_tlli(ms), tbf_name((struct gprs_rlcmac_tbf *)tbf)); + + ms_ref(ms); + + if (ms->ul_tbf) + llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->ul_tbf), &ms->old_tbfs); + + ms->ul_tbf = tbf; + + if (tbf) + ms_stop_timer(ms); + + ms_unref(ms); +} + +static void ms_attach_dl_tbf(struct GprsMs *ms, struct gprs_rlcmac_dl_tbf *tbf) +{ + if (ms->dl_tbf == tbf) + return; + + LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", + ms_tlli(ms), tbf_name((struct gprs_rlcmac_tbf *)tbf)); + + ms_ref(ms); + + if (ms->dl_tbf) + llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->dl_tbf), &ms->old_tbfs); + + ms->dl_tbf = tbf; + + if (tbf) + ms_stop_timer(ms); + + ms_unref(ms); +} + +void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf) +{ + if (tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF) + ms_attach_dl_tbf(ms, as_dl_tbf(tbf)); + else + ms_attach_ul_tbf(ms, as_ul_tbf(tbf)); +} + +void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf) +{ + if (tbf == (struct gprs_rlcmac_tbf *)(ms->ul_tbf)) { + ms->ul_tbf = NULL; + } else if (tbf == (struct gprs_rlcmac_tbf *)(ms->dl_tbf)) { + ms->dl_tbf = NULL; + } else { + bool found = false; + + struct llist_item *pos, *tmp; + llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) { + struct gprs_rlcmac_tbf *tmp_tbf = (struct gprs_rlcmac_tbf *)pos->entry; + if (tmp_tbf == tbf) { + llist_del(&pos->list); + found = true; + break; + } + } + + /* Protect against recursive calls via set_ms() */ + if (!found) + return; + } + + LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n", + ms_tlli(ms), tbf_name(tbf)); + + if (tbf_ms(tbf) == ms) + tbf_set_ms(tbf, NULL); + + if (!ms->dl_tbf && !ms->ul_tbf) { + ms_set_reserved_slots(ms, NULL, 0, 0); + + if (ms_tlli(ms) != 0) + ms_start_timer(ms); + } + + ms_update_status(ms); +} + +void ms_reset(struct GprsMs *ms) +{ + LOGP(DRLCMAC, LOGL_INFO, + "Clearing MS object, TLLI: 0x%08x, IMSI: '%s'\n", + ms_tlli(ms), ms_imsi(ms)); + + ms_stop_timer(ms); + + ms->tlli = GSM_RESERVED_TMSI; + ms->new_dl_tlli = ms->tlli; + ms->new_ul_tlli = ms->tlli; + ms->imsi[0] = '\0'; +} + +static void ms_merge_old_ms(struct GprsMs *ms, struct GprsMs *old_ms) +{ + OSMO_ASSERT(old_ms != ms); + + if (strlen(ms_imsi(ms)) == 0 && strlen(ms_imsi(old_ms)) != 0) + osmo_strlcpy(ms->imsi, ms_imsi(old_ms), sizeof(ms->imsi)); + + if (!ms_ms_class(ms) && ms_ms_class(old_ms)) + ms_set_ms_class(ms, ms_ms_class(old_ms)); + + if (!ms_egprs_ms_class(ms) && ms_egprs_ms_class(old_ms)) + ms_set_egprs_ms_class(ms, ms_egprs_ms_class(old_ms)); + + llc_queue_move_and_merge(&ms->llc_queue, &old_ms->llc_queue); + + ms_reset(old_ms); +} + +void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms) +{ + OSMO_ASSERT(old_ms != ms); + + ms_ref(old_ms); + + /* Clean up the old MS object */ + /* TODO: Use timer? */ + if (ms_ul_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms), T_MAX)) + tbf_free((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms)); + if (ms_dl_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms), T_MAX)) + tbf_free((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms)); + + ms_merge_old_ms(ms, old_ms); + + ms_unref(old_ms); +} + +void ms_set_tlli(struct GprsMs *ms, uint32_t tlli) +{ + if (tlli == ms->tlli || tlli == ms->new_ul_tlli) + return; + + if (tlli != ms->new_dl_tlli) { + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, " + "not yet confirmed\n", + ms_tlli(ms), tlli); + ms->new_ul_tlli = tlli; + return; + } + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI: 0x%08x -> 0x%08x, " + "already confirmed partly\n", + ms->tlli, tlli); + + ms->tlli = tlli; + ms->new_dl_tlli = GSM_RESERVED_TMSI; + ms->new_ul_tlli = GSM_RESERVED_TMSI; +} + +bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli) +{ + if (tlli == ms->tlli || tlli == ms->new_dl_tlli) + return false; + + if (tlli != ms->new_ul_tlli) { + /* The MS has not sent a message with the new TLLI, which may + * happen according to the spec [TODO: add reference]. */ + + LOGP(DRLCMAC, LOGL_INFO, + "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, " + "partly confirmed\n", tlli); + /* Use the network's idea of TLLI as candidate, this does not + * change the result value of tlli() */ + ms->new_dl_tlli = tlli; + return false; + } + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli); + + ms->tlli = tlli; + ms->new_dl_tlli = GSM_RESERVED_TMSI; + ms->new_ul_tlli = GSM_RESERVED_TMSI; + + return true; +} + +void ms_set_imsi(struct GprsMs *ms, const char *imsi) +{ + if (!imsi) { + LOGP(DRLCMAC, LOGL_ERROR, "Expected IMSI!\n"); + return; + } + + if (imsi[0] && strlen(imsi) < 3) { + LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI '%s'!\n", + imsi); + return; + } + + if (strcmp(imsi, ms->imsi) == 0) + return; + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI = 0x%08x, IMSI '%s' -> '%s'\n", + ms_tlli(ms), ms->imsi, imsi); + + struct GprsMs *old_ms = bts_ms_by_imsi(ms->bts, imsi); + /* Check if we are going to store a different MS object with already + existing IMSI. This is probably a bug in code calling this function, + since it should take care of this explicitly */ + if (old_ms) { + /* We cannot find ms->ms by IMSI since we know that it has a + * different IMSI */ + OSMO_ASSERT(old_ms != ms); + + LOGPMS(ms, DRLCMAC, LOGL_NOTICE, + "IMSI '%s' was already assigned to another " + "MS object: TLLI = 0x%08x, that IMSI will be removed\n", + imsi, ms_tlli(old_ms)); + + ms_merge_and_clear_ms(ms, old_ms); + } + + + osmo_strlcpy(ms->imsi, imsi, sizeof(ms->imsi)); +} + +void ms_set_ta(struct GprsMs *ms, uint8_t ta_) +{ + if (ta_ == ms->ta) + return; + + if (gsm48_ta_is_valid(ta_)) { + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI = 0x%08x, TA %d -> %d\n", + ms_tlli(ms), ms->ta, ta_); + ms->ta = ta_; + } else + LOGP(DRLCMAC, LOGL_NOTICE, + "MS object, TLLI = 0x%08x, invalid TA %d rejected (old " + "value %d kept)\n", ms_tlli(ms), ta_, ms->ta); +} + +void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_) +{ + if (ms_class_ == ms->ms_class) + return; + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI = 0x%08x, MS class %d -> %d\n", + ms_tlli(ms), ms->ms_class, ms_class_); + + ms->ms_class = ms_class_; +} + +void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_) +{ + if (ms_class_ == ms->egprs_ms_class) + return; + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI = 0x%08x, EGPRS MS class %d -> %d\n", + ms_tlli(ms), ms->egprs_ms_class, ms_class_); + + ms->egprs_ms_class = ms_class_; + + if (!bts_max_mcs_ul(ms->bts) || !bts_max_mcs_dl(ms->bts)) { + LOGPMS(ms, DRLCMAC, LOGL_DEBUG, + "Avoid enabling EGPRS because use of MCS is disabled: ul=%u dl=%u\n", + bts_max_mcs_ul(ms->bts), bts_max_mcs_dl(ms->bts)); + return; + } + + if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts))) && + mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts))) && + ms_mode(ms) != EGPRS) + { + ms_set_mode(ms, EGPRS_GMSK); + } else { + ms_set_mode(ms, EGPRS); + } + LOGPMS(ms, DRLCMAC, LOGL_INFO, "Enabled EGPRS, mode %s\n", mode_name(ms_mode(ms))); +} + +void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate) +{ + struct gprs_rlcmac_bts *bts_; + int64_t now; + enum CodingScheme max_cs_dl = ms_max_cs_dl(ms); + + OSMO_ASSERT(max_cs_dl); + bts_ = bts_data(ms->bts); + + if (error_rate < 0) + return; + + now = now_msec(); + + /* TODO: Check for TBF direction */ + /* TODO: Support different CS values for UL and DL */ + + ms->nack_rate_dl = error_rate; + + if (error_rate > bts_->cs_adj_upper_limit) { + if (mcs_chan_code(ms->current_cs_dl) > 0) { + mcs_dec_kind(&ms->current_cs_dl, ms_mode(ms)); + LOGP(DRLCMACDL, LOGL_INFO, + "MS (IMSI %s): High error rate %d%%, " + "reducing CS level to %s\n", + ms_imsi(ms), error_rate, mcs_name(ms->current_cs_dl)); + ms->last_cs_not_low = now; + } + } else if (error_rate < bts_->cs_adj_lower_limit) { + if (ms->current_cs_dl < max_cs_dl) { + if (now - ms->last_cs_not_low > 1000) { + mcs_inc_kind(&ms->current_cs_dl, ms_mode(ms)); + + LOGP(DRLCMACDL, LOGL_INFO, + "MS (IMSI %s): Low error rate %d%%, " + "increasing DL CS level to %s\n", + ms_imsi(ms), error_rate, + mcs_name(ms->current_cs_dl)); + ms->last_cs_not_low = now; + } else { + LOGP(DRLCMACDL, LOGL_DEBUG, + "MS (IMSI %s): Low error rate %d%%, " + "ignored (within blocking period)\n", + ms_imsi(ms), error_rate); + } + } + } else { + LOGP(DRLCMACDL, LOGL_DEBUG, + "MS (IMSI %s): Medium error rate %d%%, ignored\n", + ms_imsi(ms), error_rate); + ms->last_cs_not_low = now; + } +} + +enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms) +{ + OSMO_ASSERT(ms->bts != NULL); + + if (mcs_is_gprs(ms->current_cs_ul)) { + if (!bts_max_cs_ul(ms->bts)) { + return CS4; + } + + return mcs_get_gprs_by_num(bts_max_cs_ul(ms->bts)); + } + + if (!mcs_is_edge(ms->current_cs_ul)) + return UNKNOWN; + + if (bts_max_mcs_ul(ms->bts)) + return mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts)); + else if (bts_max_cs_ul(ms->bts)) + return mcs_get_gprs_by_num(bts_max_cs_ul(ms->bts)); + + return MCS4; +} + +void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme) +{ + ms->current_cs_dl = scheme; +} + +enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms) +{ + OSMO_ASSERT(ms->bts != NULL); + + if (mcs_is_gprs(ms->current_cs_dl)) { + if (!bts_max_cs_dl(ms->bts)) { + return CS4; + } + + return mcs_get_gprs_by_num(bts_max_cs_dl(ms->bts)); + } + + if (!mcs_is_edge(ms->current_cs_dl)) + return UNKNOWN; + + if (bts_max_mcs_dl(ms->bts)) + return mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts)); + else if (bts_max_cs_dl(ms->bts)) + return mcs_get_gprs_by_num(bts_max_cs_dl(ms->bts)); + + return MCS4; +} + +void ms_update_cs_ul(struct GprsMs *ms, const struct pcu_l1_meas *meas) +{ + struct gprs_rlcmac_bts *bts_; + enum CodingScheme max_cs_ul = ms_max_cs_ul(ms); + + int old_link_qual; + int low; + int high; + enum CodingScheme new_cs_ul = ms->current_cs_ul; + uint8_t current_cs = mcs_chan_code(ms->current_cs_ul); + + bts_ = bts_data(ms->bts); + + if (!max_cs_ul) { + LOGP(DRLCMACMEAS, LOGL_ERROR, + "max_cs_ul cannot be derived (current UL CS: %s)\n", + mcs_name(ms->current_cs_ul)); + return; + } + + if (!ms->current_cs_ul) { + LOGP(DRLCMACMEAS, LOGL_ERROR, + "Unable to update UL (M)CS because it's not set: %s\n", + mcs_name(ms->current_cs_ul)); + return; + } + + if (!meas->have_link_qual) { + LOGP(DRLCMACMEAS, LOGL_ERROR, + "Unable to update UL (M)CS %s because we don't have link quality measurements.\n", + mcs_name(ms->current_cs_ul)); + return; + } + + if (mcs_is_gprs(ms->current_cs_ul)) { + if (current_cs >= MAX_GPRS_CS) + current_cs = MAX_GPRS_CS - 1; + low = bts_->cs_lqual_ranges[current_cs].low; + high = bts_->cs_lqual_ranges[current_cs].high; + } else if (mcs_is_edge(ms->current_cs_ul)) { + if (current_cs >= MAX_EDGE_MCS) + current_cs = MAX_EDGE_MCS - 1; + low = bts_->mcs_lqual_ranges[current_cs].low; + high = bts_->mcs_lqual_ranges[current_cs].high; + } else { + LOGP(DRLCMACMEAS, LOGL_ERROR, + "Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n", + mcs_name(ms->current_cs_ul)); + return; + } + + /* To avoid rapid changes of the coding scheme, we also take + * the old link quality value into account (if present). */ + if (ms->l1_meas.have_link_qual) + old_link_qual = ms->l1_meas.link_qual; + else + old_link_qual = meas->link_qual; + + if (meas->link_qual < low && old_link_qual < low) + mcs_dec_kind(&new_cs_ul, ms_mode(ms)); + else if (meas->link_qual > high && old_link_qual > high && + ms->current_cs_ul < max_cs_ul) + mcs_inc_kind(&new_cs_ul, ms_mode(ms)); + + if (ms->current_cs_ul != new_cs_ul) { + LOGPMS(ms, DRLCMACMEAS, LOGL_INFO, + "Link quality %ddB (old %ddB) left window [%d, %d], " + "modifying uplink CS level: %s -> %s\n", + meas->link_qual, old_link_qual, + low, high, + mcs_name(ms->current_cs_ul), mcs_name(new_cs_ul)); + + ms->current_cs_ul = new_cs_ul; + } +} + +void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas) +{ + unsigned i; + + ms_update_cs_ul(ms, meas); + + if (meas->have_rssi) + pcu_l1_meas_set_rssi(&ms->l1_meas, meas->rssi); + if (meas->have_bto) + pcu_l1_meas_set_bto(&ms->l1_meas, meas->bto); + if (meas->have_ber) + pcu_l1_meas_set_ber(&ms->l1_meas, meas->ber); + if (meas->have_link_qual) + pcu_l1_meas_set_link_qual(&ms->l1_meas, meas->link_qual); + + if (meas->have_ms_rx_qual) + pcu_l1_meas_set_ms_rx_qual(&ms->l1_meas, meas->ms_rx_qual); + if (meas->have_ms_c_value) + pcu_l1_meas_set_ms_c_value(&ms->l1_meas, meas->ms_c_value); + if (meas->have_ms_sign_var) + pcu_l1_meas_set_ms_sign_var(&ms->l1_meas, meas->ms_sign_var); + + if (meas->have_ms_i_level) { + for (i = 0; i < ARRAY_SIZE(meas->ts); ++i) { + if (meas->ts[i].have_ms_i_level) + pcu_l1_meas_set_ms_i_level(&ms->l1_meas, i, meas->ts[i].ms_i_level); + else + ms->l1_meas.ts[i].have_ms_i_level = 0; + } + } +} + +enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms) +{ + enum CodingScheme cs = ms->current_cs_dl; + size_t unencoded_octets; + + if (!ms->bts) + return cs; + + unencoded_octets = llc_queue_octets(&ms->llc_queue); + + /* If the DL TBF is active, add number of unencoded chunk octets */ + if (ms->dl_tbf) + unencoded_octets += llc_chunk_size(tbf_llc((struct gprs_rlcmac_tbf *)ms->dl_tbf)); + + /* There are many unencoded octets, don't reduce */ + if (unencoded_octets >= bts_data(ms->bts)->cs_downgrade_threshold) + return cs; + + /* RF conditions are good, don't reduce */ + if (ms->nack_rate_dl < bts_data(ms->bts)->cs_adj_lower_limit) + return cs; + + /* The throughput would probably be better if the CS level was reduced */ + mcs_dec_kind(&cs, ms_mode(ms)); + + /* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */ + if (cs == CS2) + mcs_dec_kind(&cs, ms_mode(ms)); + + return cs; +} + +int ms_first_common_ts(const struct GprsMs *ms) +{ + if (ms->dl_tbf) + return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->dl_tbf); + + if (ms->ul_tbf) + return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->ul_tbf); + + return -1; +} + +uint8_t ms_dl_slots(const struct GprsMs *ms) +{ + uint8_t slots = 0; + + if (ms->dl_tbf) + slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf); + + if (ms->ul_tbf) + slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf); + + return slots; +} + +uint8_t ms_ul_slots(const struct GprsMs *ms) +{ + uint8_t slots = 0; + + if (ms->dl_tbf) + slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf); + + if (ms->ul_tbf) + slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf); + + return slots; +} + +uint8_t ms_current_pacch_slots(const struct GprsMs *ms) +{ + uint8_t slots = 0; + + bool is_dl_active = ms->dl_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->dl_tbf); + bool is_ul_active = ms->ul_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->ul_tbf); + + if (!is_dl_active && !is_ul_active) + return 0; + + /* see TS 44.060, 8.1.1.2.2 */ + if (is_dl_active && !is_ul_active) + slots = tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf); + else if (!is_dl_active && is_ul_active) + slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf); + else + slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf) & + tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf); + + /* Assume a multislot class 1 device */ + /* TODO: For class 2 devices, this could be removed */ + slots = pcu_lsb(slots); + + return slots; +} + +void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx, + uint8_t ul_slots, uint8_t dl_slots) +{ + if (ms->current_trx) { + bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF, + ms->reserved_dl_slots); + bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF, + ms->reserved_ul_slots); + ms->reserved_dl_slots = 0; + ms->reserved_ul_slots = 0; + } + ms->current_trx = trx; + if (trx) { + ms->reserved_dl_slots = dl_slots; + ms->reserved_ul_slots = ul_slots; + bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF, + ms->reserved_dl_slots); + bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF, + ms->reserved_ul_slots); + } +} + +struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir) +{ + switch (dir) { + case GPRS_RLCMAC_DL_TBF: return (struct gprs_rlcmac_tbf *)ms->dl_tbf; + case GPRS_RLCMAC_UL_TBF: return (struct gprs_rlcmac_tbf *)ms->ul_tbf; + } + + return NULL; +} diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp deleted file mode 100644 index c891cdfd..00000000 --- a/src/gprs_ms.cpp +++ /dev/null @@ -1,900 +0,0 @@ -/* gprs_ms.cpp - * - * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH - * Author: Jacob Erlbeck <jerlbeck@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 "gprs_ms.h" -#include "bts.h" -#include "tbf.h" -#include "tbf_ul.h" -#include "gprs_debug.h" -#include "gprs_codel.h" -#include "pcu_utils.h" - -#include <time.h> - -extern "C" { - #include <osmocom/core/talloc.h> - #include <osmocom/core/utils.h> - #include <osmocom/core/timer.h> - #include <osmocom/gsm/protocol/gsm_04_08.h> - #include <osmocom/gsm/gsm48.h> - #include <osmocom/core/logging.h> - #include "coding_scheme.h" -} - -#define GPRS_CODEL_SLOW_INTERVAL_MS 4000 - -extern void *tall_pcu_ctx; - -static int64_t now_msec() -{ - struct timespec ts; - osmo_clock_gettime(CLOCK_MONOTONIC, &ts); - - return int64_t(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000; -} - -struct GprsMsDefaultCallback: public GprsMs::Callback { - virtual void ms_idle(class GprsMs *ms) { - delete ms; - } - virtual void ms_active(class GprsMs *) {} -}; - -static GprsMsDefaultCallback gprs_default_cb; - -GprsMs::Guard::Guard(GprsMs *ms) : - m_ms(ms ? ms->ref() : NULL) -{ -} - -GprsMs::Guard::~Guard() -{ - if (m_ms) - m_ms->unref(); -} - -bool GprsMs::Guard::is_idle() const -{ - if (!m_ms) - return true; - - return !m_ms->m_ul_tbf && !m_ms->m_dl_tbf && m_ms->m_ref == 1; -} - -void GprsMs::timeout(void *priv_) -{ - GprsMs *ms = static_cast<GprsMs *>(priv_); - - LOGP(DRLCMAC, LOGL_INFO, "Timeout for MS object, TLLI = 0x%08x\n", - ms->tlli()); - - if (ms->m_timer.data) { - ms->m_timer.data = NULL; - ms->unref(); - } -} - -GprsMs::GprsMs(BTS *bts, uint32_t tlli) : - m_bts(bts), - m_cb(&gprs_default_cb), - m_ul_tbf(NULL), - m_dl_tbf(NULL), - m_tlli(tlli), - m_new_ul_tlli(GSM_RESERVED_TMSI), - m_new_dl_tlli(GSM_RESERVED_TMSI), - m_ta(GSM48_TA_INVALID), - m_ms_class(0), - m_egprs_ms_class(0), - m_current_cs_ul(UNKNOWN), - m_current_cs_dl(UNKNOWN), - m_is_idle(true), - m_ref(0), - m_list(this), - m_delay(0), - m_nack_rate_dl(0), - m_reserved_dl_slots(0), - m_reserved_ul_slots(0), - m_current_trx(NULL), - m_codel_state(NULL), - m_mode(GPRS), - m_dl_ctrl_msg(0) -{ - int codel_interval = LLC_CODEL_USE_DEFAULT; - - LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli); - - m_imsi[0] = '\0'; - memset(&m_timer, 0, sizeof(m_timer)); - m_timer.cb = GprsMs::timeout; - m_llc_queue.init(); - - set_mode(m_mode); - - if (m_bts) - codel_interval = m_bts->bts_data()->llc_codel_interval_msec; - - if (codel_interval) { - if (codel_interval == LLC_CODEL_USE_DEFAULT) - codel_interval = GPRS_CODEL_SLOW_INTERVAL_MS; - m_codel_state = talloc(this, struct gprs_codel); - gprs_codel_init(m_codel_state); - gprs_codel_set_interval(m_codel_state, codel_interval); - } - m_last_cs_not_low = now_msec(); - app_info_pending = false; -} - -GprsMs::~GprsMs() -{ - LListHead<gprs_rlcmac_tbf> *pos, *tmp; - - LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", tlli()); - - set_reserved_slots(NULL, 0, 0); - - if (osmo_timer_pending(&m_timer)) - osmo_timer_del(&m_timer); - - if (m_ul_tbf) { - m_ul_tbf->set_ms(NULL); - m_ul_tbf = NULL; - } - - if (m_dl_tbf) { - m_dl_tbf->set_ms(NULL); - m_dl_tbf = NULL; - } - - llist_for_each_safe(pos, tmp, &m_old_tbfs) - pos->entry()->set_ms(NULL); - - m_llc_queue.clear(m_bts); -} - -void* GprsMs::operator new(size_t size) -{ - static void *tall_ms_ctx = NULL; - if (!tall_ms_ctx) - tall_ms_ctx = talloc_named_const(tall_pcu_ctx, 0, __PRETTY_FUNCTION__); - - return talloc_size(tall_ms_ctx, size); -} - -void GprsMs::operator delete(void* p) -{ - talloc_free(p); -} - -GprsMs *GprsMs::ref() -{ - m_ref += 1; - return this; -} - -void GprsMs::unref() -{ - OSMO_ASSERT(m_ref >= 0); - m_ref -= 1; - if (m_ref == 0) - update_status(); -} - -void GprsMs::start_timer() -{ - if (m_delay == 0) - return; - - if (!m_timer.data) - m_timer.data = ref(); - - osmo_timer_schedule(&m_timer, m_delay, 0); -} - -void GprsMs::stop_timer() -{ - if (!m_timer.data) - return; - - osmo_timer_del(&m_timer); - m_timer.data = NULL; - unref(); -} - -void GprsMs::set_mode(enum mcs_kind mode) -{ - m_mode = mode; - - if (!m_bts) - return; - - switch (m_mode) { - case GPRS: - if (!mcs_is_gprs(m_current_cs_ul)) { - m_current_cs_ul = mcs_get_gprs_by_num( - m_bts->bts_data()->initial_cs_ul); - if (!mcs_is_valid(m_current_cs_ul)) - m_current_cs_ul = CS1; - } - if (!mcs_is_gprs(m_current_cs_dl)) { - m_current_cs_dl = mcs_get_gprs_by_num( - m_bts->bts_data()->initial_cs_dl); - if (!mcs_is_valid(m_current_cs_dl)) - m_current_cs_dl = CS1; - } - break; - - case EGPRS_GMSK: - case EGPRS: - if (!mcs_is_edge(m_current_cs_ul)) { - m_current_cs_ul = mcs_get_egprs_by_num( - m_bts->bts_data()->initial_mcs_ul); - if (!mcs_is_valid(m_current_cs_ul)) - m_current_cs_ul = MCS1; - } - if (!mcs_is_edge(m_current_cs_dl)) { - m_current_cs_dl = mcs_get_egprs_by_num( - m_bts->bts_data()->initial_mcs_dl); - if (!mcs_is_valid(m_current_cs_dl)) - m_current_cs_dl = MCS1; - } - break; - } -} - -void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf) -{ - if (tbf->direction == GPRS_RLCMAC_DL_TBF) - attach_dl_tbf(as_dl_tbf(tbf)); - else - attach_ul_tbf(as_ul_tbf(tbf)); -} - -void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf) -{ - if (m_ul_tbf == tbf) - return; - - LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", - tlli(), tbf->name()); - - Guard guard(this); - - if (m_ul_tbf) - llist_add_tail(&m_ul_tbf->ms_list(), &m_old_tbfs); - - m_ul_tbf = tbf; - - if (tbf) - stop_timer(); -} - -void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf) -{ - if (m_dl_tbf == tbf) - return; - - LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", - tlli(), tbf->name()); - - Guard guard(this); - - if (m_dl_tbf) - llist_add_tail(&m_dl_tbf->ms_list(), &m_old_tbfs); - - m_dl_tbf = tbf; - - if (tbf) - stop_timer(); -} - -void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf) -{ - if (tbf == static_cast<gprs_rlcmac_tbf *>(m_ul_tbf)) { - m_ul_tbf = NULL; - } else if (tbf == static_cast<gprs_rlcmac_tbf *>(m_dl_tbf)) { - m_dl_tbf = NULL; - } else { - bool found = false; - - LListHead<gprs_rlcmac_tbf> *pos, *tmp; - llist_for_each_safe(pos, tmp, &m_old_tbfs) { - if (pos->entry() == tbf) { - llist_del(pos); - found = true; - break; - } - } - - /* Protect against recursive calls via set_ms() */ - if (!found) - return; - } - - LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n", - tlli(), tbf->name()); - - if (tbf->ms() == this) - tbf->set_ms(NULL); - - if (!m_dl_tbf && !m_ul_tbf) { - set_reserved_slots(NULL, 0, 0); - - if (tlli() != 0) - start_timer(); - } - - update_status(); -} - -void GprsMs::update_status() -{ - if (m_ref > 0) - return; - - if (is_idle() && !m_is_idle) { - m_is_idle = true; - m_cb->ms_idle(this); - /* this can be deleted by now, do not access it */ - return; - } - - if (!is_idle() && m_is_idle) { - m_is_idle = false; - m_cb->ms_active(this); - } -} - -void GprsMs::reset() -{ - LOGP(DRLCMAC, LOGL_INFO, - "Clearing MS object, TLLI: 0x%08x, IMSI: '%s'\n", - tlli(), imsi()); - - stop_timer(); - - m_tlli = GSM_RESERVED_TMSI; - m_new_dl_tlli = m_tlli; - m_new_ul_tlli = m_tlli; - m_imsi[0] = '\0'; -} - -void GprsMs::merge_old_ms(GprsMs *old_ms) -{ - OSMO_ASSERT(old_ms != this); - - if (strlen(imsi()) == 0 && strlen(old_ms->imsi()) != 0) - osmo_strlcpy(m_imsi, old_ms->imsi(), sizeof(m_imsi)); - - if (!ms_class() && old_ms->ms_class()) - set_ms_class(old_ms->ms_class()); - - if (!egprs_ms_class() && old_ms->egprs_ms_class()) - set_egprs_ms_class(old_ms->egprs_ms_class()); - - m_llc_queue.move_and_merge(&old_ms->m_llc_queue); - - old_ms->reset(); -} - -void GprsMs::merge_and_clear_ms(GprsMs *old_ms) -{ - OSMO_ASSERT(old_ms != this); - - GprsMs::Guard guard_old(old_ms); - - /* Clean up the old MS object */ - /* TODO: Use timer? */ - if (old_ms->ul_tbf() && !old_ms->ul_tbf()->timers_pending(T_MAX)) - tbf_free(old_ms->ul_tbf()); - if (old_ms->dl_tbf() && !old_ms->dl_tbf()->timers_pending(T_MAX)) - tbf_free(old_ms->dl_tbf()); - - merge_old_ms(old_ms); -} - -void GprsMs::set_tlli(uint32_t tlli) -{ - if (tlli == m_tlli || tlli == m_new_ul_tlli) - return; - - if (tlli != m_new_dl_tlli) { - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, " - "not yet confirmed\n", - this->tlli(), tlli); - m_new_ul_tlli = tlli; - return; - } - - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI: 0x%08x -> 0x%08x, " - "already confirmed partly\n", - m_tlli, tlli); - - m_tlli = tlli; - m_new_dl_tlli = GSM_RESERVED_TMSI; - m_new_ul_tlli = GSM_RESERVED_TMSI; -} - -bool GprsMs::confirm_tlli(uint32_t tlli) -{ - if (tlli == m_tlli || tlli == m_new_dl_tlli) - return false; - - if (tlli != m_new_ul_tlli) { - /* The MS has not sent a message with the new TLLI, which may - * happen according to the spec [TODO: add reference]. */ - - LOGP(DRLCMAC, LOGL_INFO, - "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, " - "partly confirmed\n", tlli); - /* Use the network's idea of TLLI as candidate, this does not - * change the result value of tlli() */ - m_new_dl_tlli = tlli; - return false; - } - - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli); - - m_tlli = tlli; - m_new_dl_tlli = GSM_RESERVED_TMSI; - m_new_ul_tlli = GSM_RESERVED_TMSI; - - return true; -} - -void GprsMs::set_imsi(const char *imsi) -{ - if (!imsi) { - LOGP(DRLCMAC, LOGL_ERROR, "Expected IMSI!\n"); - return; - } - - if (imsi[0] && strlen(imsi) < 3) { - LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI '%s'!\n", - imsi); - return; - } - - if (strcmp(imsi, m_imsi) == 0) - return; - - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI = 0x%08x, IMSI '%s' -> '%s'\n", - tlli(), m_imsi, imsi); - - GprsMs *old_ms = m_bts->ms_store().get_ms(0, 0, imsi); - /* Check if we are going to store a different MS object with already - existing IMSI. This is probably a bug in code calling this function, - since it should take care of this explicitly */ - if (old_ms) { - /* We cannot find m_ms by IMSI since we know that it has a - * different IMSI */ - OSMO_ASSERT(old_ms != this); - - LOGPMS(this, DRLCMAC, LOGL_NOTICE, - "IMSI '%s' was already assigned to another " - "MS object: TLLI = 0x%08x, that IMSI will be removed\n", - imsi, old_ms->tlli()); - - merge_and_clear_ms(old_ms); - } - - - osmo_strlcpy(m_imsi, imsi, sizeof(m_imsi)); -} - -void GprsMs::set_ta(uint8_t ta_) -{ - if (ta_ == m_ta) - return; - - if (gsm48_ta_is_valid(ta_)) { - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI = 0x%08x, TA %d -> %d\n", - tlli(), m_ta, ta_); - m_ta = ta_; - } else - LOGP(DRLCMAC, LOGL_NOTICE, - "MS object, TLLI = 0x%08x, invalid TA %d rejected (old " - "value %d kept)\n", tlli(), ta_, m_ta); -} - -void GprsMs::set_ms_class(uint8_t ms_class_) -{ - if (ms_class_ == m_ms_class) - return; - - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI = 0x%08x, MS class %d -> %d\n", - tlli(), m_ms_class, ms_class_); - - m_ms_class = ms_class_; -} - -void GprsMs::set_egprs_ms_class(uint8_t ms_class_) -{ - if (ms_class_ == m_egprs_ms_class) - return; - - LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI = 0x%08x, EGPRS MS class %d -> %d\n", - tlli(), m_egprs_ms_class, ms_class_); - - m_egprs_ms_class = ms_class_; - - if (!m_bts->max_mcs_ul() || !m_bts->max_mcs_dl()) { - LOGPMS(this, DRLCMAC, LOGL_DEBUG, - "Avoid enabling EGPRS because use of MCS is disabled: ul=%u dl=%u\n", - m_bts->max_mcs_ul(), m_bts->max_mcs_dl()); - return; - } - - if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(m_bts->max_mcs_ul())) && - mcs_is_edge_gmsk(mcs_get_egprs_by_num(m_bts->max_mcs_dl())) && - mode() != EGPRS) - { - set_mode(EGPRS_GMSK); - } else { - set_mode(EGPRS); - } - LOGPMS(this, DRLCMAC, LOGL_INFO, "Enabled EGPRS, mode %s\n", mode_name(mode())); -} - -void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate) -{ - struct gprs_rlcmac_bts *bts_data; - int64_t now; - enum CodingScheme max_cs_dl = this->max_cs_dl(); - - OSMO_ASSERT(max_cs_dl); - bts_data = m_bts->bts_data(); - - if (error_rate < 0) - return; - - now = now_msec(); - - /* TODO: Check for TBF direction */ - /* TODO: Support different CS values for UL and DL */ - - m_nack_rate_dl = error_rate; - - if (error_rate > bts_data->cs_adj_upper_limit) { - if (mcs_chan_code(m_current_cs_dl) > 0) { - mcs_dec_kind(&m_current_cs_dl, mode()); - LOGP(DRLCMACDL, LOGL_INFO, - "MS (IMSI %s): High error rate %d%%, " - "reducing CS level to %s\n", - imsi(), error_rate, mcs_name(m_current_cs_dl)); - m_last_cs_not_low = now; - } - } else if (error_rate < bts_data->cs_adj_lower_limit) { - if (m_current_cs_dl < max_cs_dl) { - if (now - m_last_cs_not_low > 1000) { - mcs_inc_kind(&m_current_cs_dl, mode()); - - LOGP(DRLCMACDL, LOGL_INFO, - "MS (IMSI %s): Low error rate %d%%, " - "increasing DL CS level to %s\n", - imsi(), error_rate, - mcs_name(m_current_cs_dl)); - m_last_cs_not_low = now; - } else { - LOGP(DRLCMACDL, LOGL_DEBUG, - "MS (IMSI %s): Low error rate %d%%, " - "ignored (within blocking period)\n", - imsi(), error_rate); - } - } - } else { - LOGP(DRLCMACDL, LOGL_DEBUG, - "MS (IMSI %s): Medium error rate %d%%, ignored\n", - imsi(), error_rate); - m_last_cs_not_low = now; - } -} - -enum CodingScheme GprsMs::max_cs_ul() const -{ - OSMO_ASSERT(m_bts != NULL); - - if (mcs_is_gprs(m_current_cs_ul)) { - if (!m_bts->max_cs_ul()) { - return CS4; - } - - return mcs_get_gprs_by_num(m_bts->max_cs_ul()); - } - - if (!mcs_is_edge(m_current_cs_ul)) - return UNKNOWN; - - if (m_bts->max_mcs_ul()) - return mcs_get_egprs_by_num(m_bts->max_mcs_ul()); - else if (m_bts->max_cs_ul()) - return mcs_get_gprs_by_num(m_bts->max_cs_ul()); - - return MCS4; -} - -void GprsMs::set_current_cs_dl(enum CodingScheme scheme) -{ - m_current_cs_dl = scheme; -} - -enum CodingScheme GprsMs::max_cs_dl() const -{ - OSMO_ASSERT(m_bts != NULL); - - if (mcs_is_gprs(m_current_cs_dl)) { - if (!m_bts->max_cs_dl()) { - return CS4; - } - - return mcs_get_gprs_by_num(m_bts->max_cs_dl()); - } - - if (!mcs_is_edge(m_current_cs_dl)) - return UNKNOWN; - - if (m_bts->max_mcs_dl()) - return mcs_get_egprs_by_num(m_bts->max_mcs_dl()); - else if (m_bts->max_cs_dl()) - return mcs_get_gprs_by_num(m_bts->max_cs_dl()); - - return MCS4; -} - -void GprsMs::update_cs_ul(const pcu_l1_meas *meas) -{ - struct gprs_rlcmac_bts *bts_data; - enum CodingScheme max_cs_ul = this->max_cs_ul(); - - int old_link_qual; - int low; - int high; - enum CodingScheme new_cs_ul = m_current_cs_ul; - uint8_t current_cs = mcs_chan_code(m_current_cs_ul); - - bts_data = m_bts->bts_data(); - - if (!max_cs_ul) { - LOGP(DRLCMACMEAS, LOGL_ERROR, - "max_cs_ul cannot be derived (current UL CS: %s)\n", - mcs_name(m_current_cs_ul)); - return; - } - - if (!m_current_cs_ul) { - LOGP(DRLCMACMEAS, LOGL_ERROR, - "Unable to update UL (M)CS because it's not set: %s\n", - mcs_name(m_current_cs_ul)); - return; - } - - if (!meas->have_link_qual) { - LOGP(DRLCMACMEAS, LOGL_ERROR, - "Unable to update UL (M)CS %s because we don't have link quality measurements.\n", - mcs_name(m_current_cs_ul)); - return; - } - - if (mcs_is_gprs(m_current_cs_ul)) { - if (current_cs >= MAX_GPRS_CS) - current_cs = MAX_GPRS_CS - 1; - low = bts_data->cs_lqual_ranges[current_cs].low; - high = bts_data->cs_lqual_ranges[current_cs].high; - } else if (mcs_is_edge(m_current_cs_ul)) { - if (current_cs >= MAX_EDGE_MCS) - current_cs = MAX_EDGE_MCS - 1; - low = bts_data->mcs_lqual_ranges[current_cs].low; - high = bts_data->mcs_lqual_ranges[current_cs].high; - } else { - LOGP(DRLCMACMEAS, LOGL_ERROR, - "Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n", - mcs_name(m_current_cs_ul)); - return; - } - - /* To avoid rapid changes of the coding scheme, we also take - * the old link quality value into account (if present). */ - if (m_l1_meas.have_link_qual) - old_link_qual = m_l1_meas.link_qual; - else - old_link_qual = meas->link_qual; - - if (meas->link_qual < low && old_link_qual < low) - mcs_dec_kind(&new_cs_ul, mode()); - else if (meas->link_qual > high && old_link_qual > high && - m_current_cs_ul < max_cs_ul) - mcs_inc_kind(&new_cs_ul, mode()); - - if (m_current_cs_ul != new_cs_ul) { - LOGPMS(this, DRLCMACMEAS, LOGL_INFO, - "Link quality %ddB (old %ddB) left window [%d, %d], " - "modifying uplink CS level: %s -> %s\n", - meas->link_qual, old_link_qual, - low, high, - mcs_name(m_current_cs_ul), mcs_name(new_cs_ul)); - - m_current_cs_ul = new_cs_ul; - } -} - -void GprsMs::update_l1_meas(const pcu_l1_meas *meas) -{ - unsigned i; - - update_cs_ul(meas); - - if (meas->have_rssi) - m_l1_meas.set_rssi(meas->rssi); - if (meas->have_bto) - m_l1_meas.set_bto(meas->bto); - if (meas->have_ber) - m_l1_meas.set_ber(meas->ber); - if (meas->have_link_qual) - m_l1_meas.set_link_qual(meas->link_qual); - - if (meas->have_ms_rx_qual) - m_l1_meas.set_ms_rx_qual(meas->ms_rx_qual); - if (meas->have_ms_c_value) - m_l1_meas.set_ms_c_value(meas->ms_c_value); - if (meas->have_ms_sign_var) - m_l1_meas.set_ms_sign_var(meas->ms_sign_var); - - if (meas->have_ms_i_level) { - for (i = 0; i < ARRAY_SIZE(meas->ts); ++i) { - if (meas->ts[i].have_ms_i_level) - m_l1_meas.set_ms_i_level(i, meas->ts[i].ms_i_level); - else - m_l1_meas.ts[i].have_ms_i_level = 0; - } - } -} - -enum CodingScheme GprsMs::current_cs_dl() const -{ - enum CodingScheme cs = m_current_cs_dl; - size_t unencoded_octets; - - if (!m_bts) - return cs; - - unencoded_octets = m_llc_queue.octets(); - - /* If the DL TBF is active, add number of unencoded chunk octets */ - if (m_dl_tbf) - unencoded_octets += m_dl_tbf->m_llc.chunk_size(); - - /* There are many unencoded octets, don't reduce */ - if (unencoded_octets >= m_bts->bts_data()->cs_downgrade_threshold) - return cs; - - /* RF conditions are good, don't reduce */ - if (m_nack_rate_dl < m_bts->bts_data()->cs_adj_lower_limit) - return cs; - - /* The throughput would probably be better if the CS level was reduced */ - mcs_dec_kind(&cs, mode()); - - /* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */ - if (cs == CS2) - mcs_dec_kind(&cs, mode()); - - return cs; -} - -int GprsMs::first_common_ts() const -{ - if (m_dl_tbf) - return m_dl_tbf->first_common_ts; - - if (m_ul_tbf) - return m_ul_tbf->first_common_ts; - - return -1; -} - -uint8_t GprsMs::dl_slots() const -{ - uint8_t slots = 0; - - if (m_dl_tbf) - slots |= m_dl_tbf->dl_slots(); - - if (m_ul_tbf) - slots |= m_ul_tbf->dl_slots(); - - return slots; -} - -uint8_t GprsMs::ul_slots() const -{ - uint8_t slots = 0; - - if (m_dl_tbf) - slots |= m_dl_tbf->ul_slots(); - - if (m_ul_tbf) - slots |= m_ul_tbf->ul_slots(); - - return slots; -} - -uint8_t GprsMs::current_pacch_slots() const -{ - uint8_t slots = 0; - - bool is_dl_active = m_dl_tbf && m_dl_tbf->is_tfi_assigned(); - bool is_ul_active = m_ul_tbf && m_ul_tbf->is_tfi_assigned(); - - if (!is_dl_active && !is_ul_active) - return 0; - - /* see TS 44.060, 8.1.1.2.2 */ - if (is_dl_active && !is_ul_active) - slots = m_dl_tbf->dl_slots(); - else if (!is_dl_active && is_ul_active) - slots = m_ul_tbf->ul_slots(); - else - slots = m_ul_tbf->ul_slots() & m_dl_tbf->dl_slots(); - - /* Assume a multislot class 1 device */ - /* TODO: For class 2 devices, this could be removed */ - slots = pcu_lsb(slots); - - return slots; -} - -void GprsMs::set_reserved_slots(gprs_rlcmac_trx *trx, - uint8_t ul_slots, uint8_t dl_slots) -{ - if (m_current_trx) { - m_current_trx->unreserve_slots(GPRS_RLCMAC_DL_TBF, - m_reserved_dl_slots); - m_current_trx->unreserve_slots(GPRS_RLCMAC_UL_TBF, - m_reserved_ul_slots); - m_reserved_dl_slots = 0; - m_reserved_ul_slots = 0; - } - m_current_trx = trx; - if (trx) { - m_reserved_dl_slots = dl_slots; - m_reserved_ul_slots = ul_slots; - m_current_trx->reserve_slots(GPRS_RLCMAC_DL_TBF, - m_reserved_dl_slots); - m_current_trx->reserve_slots(GPRS_RLCMAC_UL_TBF, - m_reserved_ul_slots); - } -} - -gprs_rlcmac_tbf *GprsMs::tbf(enum gprs_rlcmac_tbf_direction dir) const -{ - switch (dir) { - case GPRS_RLCMAC_DL_TBF: return m_dl_tbf; - case GPRS_RLCMAC_UL_TBF: return m_ul_tbf; - } - - return NULL; -} diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 8b8940bb..ade3f3ba 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -1,6 +1,6 @@ /* gprs_ms.h * - * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH + * Copyright (C) 2015-2020 by Sysmocom s.f.m.c. GmbH * Author: Jacob Erlbeck <jerlbeck@sysmocom.de> * * This program is free software; you can redistribute it and/or @@ -22,22 +22,23 @@ struct gprs_codel; -#include "cxx_linuxlist.h" #include "llc.h" #include "tbf.h" #include "tbf_ul.h" #include "tbf_dl.h" #include "pcu_l1_if.h" +#ifdef __cplusplus extern "C" { - #include <osmocom/core/timer.h> - #include <osmocom/core/linuxlist.h> +#endif - #include <osmocom/gsm/protocol/gsm_23_003.h> - #include <osmocom/gsm/gsm48.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/linuxlist.h> - #include "coding_scheme.h" -} +#include <osmocom/gsm/protocol/gsm_23_003.h> +#include <osmocom/gsm/gsm48.h> + +#include "coding_scheme.h" #include <stdint.h> #include <stddef.h> @@ -45,268 +46,207 @@ extern "C" { struct BTS; struct gprs_rlcmac_trx; +struct GprsMs; -class GprsMs { -public: - struct Callback { - virtual void ms_idle(class GprsMs *) = 0; - virtual void ms_active(class GprsMs *) = 0; - }; - - class Guard { - public: - Guard(GprsMs *ms); - ~Guard(); - - bool is_idle() const; - - private: - GprsMs * const m_ms; - }; - - GprsMs(BTS *bts, uint32_t tlli); - ~GprsMs(); - - void set_callback(Callback *cb) {m_cb = cb;} - - void merge_and_clear_ms(GprsMs *old_ms); - - gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;} - gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;} - gprs_rlcmac_tbf *tbf(enum gprs_rlcmac_tbf_direction dir) const; - uint32_t tlli() const; - void set_tlli(uint32_t tlli); - bool confirm_tlli(uint32_t tlli); - bool check_tlli(uint32_t tlli); - - void reset(); - enum mcs_kind mode() const; - void set_mode(enum mcs_kind mode); - - const char *imsi() const; - void set_imsi(const char *imsi); - - uint8_t ta() const; - void set_ta(uint8_t ta); - uint8_t ms_class() const; - uint8_t egprs_ms_class() const; - void set_ms_class(uint8_t ms_class); - void set_egprs_ms_class(uint8_t ms_class); - void set_current_cs_dl(enum CodingScheme scheme); +struct gpr_ms_callback { + void (*ms_idle)(struct GprsMs *); + void (*ms_active)(struct GprsMs *); +}; - enum CodingScheme current_cs_ul() const; - enum CodingScheme current_cs_dl() const; - enum CodingScheme max_cs_ul() const; - enum CodingScheme max_cs_dl() const; +struct GprsMs { + struct llist_head list; /* list of all GprsMs */ + struct gpr_ms_callback cb; + bool app_info_pending; - int first_common_ts() const; - uint8_t dl_slots() const; - uint8_t ul_slots() const; - uint8_t reserved_dl_slots() const; - uint8_t reserved_ul_slots() const; - uint8_t current_pacch_slots() const; - gprs_rlcmac_trx *current_trx() const; - void set_reserved_slots(gprs_rlcmac_trx *trx, - uint8_t ul_slots, uint8_t dl_slots); + struct BTS *bts; + struct gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_dl_tbf *dl_tbf; + struct llist_head old_tbfs; /* list of gprs_rlcmac_tbf */ - gprs_llc_queue *llc_queue(); - const gprs_llc_queue *llc_queue() const; - gprs_codel *codel_state() const; + uint32_t tlli; + uint32_t new_ul_tlli; + uint32_t new_dl_tlli; - void set_timeout(unsigned secs); + /* store IMSI for look-up and PCH retransmission */ + char imsi[OSMO_IMSI_BUF_SIZE]; + uint8_t ta; + uint8_t ms_class; + uint8_t egprs_ms_class; + /* current coding scheme */ + enum CodingScheme current_cs_ul; + enum CodingScheme current_cs_dl; - void attach_tbf(gprs_rlcmac_tbf *tbf); - void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf); - void attach_dl_tbf(gprs_rlcmac_dl_tbf *tbf); + struct gprs_llc_queue llc_queue; - void detach_tbf(gprs_rlcmac_tbf *tbf); + bool is_idle; + int ref; + struct osmo_timer_list timer; + unsigned delay; - void update_error_rate(gprs_rlcmac_tbf *tbf, int percent); + int64_t last_cs_not_low; - bool is_idle() const; - bool need_dl_tbf() const; + struct pcu_l1_meas l1_meas; + unsigned nack_rate_dl; + uint8_t reserved_dl_slots; + uint8_t reserved_ul_slots; + struct gprs_rlcmac_trx *current_trx; - void* operator new(size_t num); - void operator delete(void* p); + struct gprs_codel *codel_state; + enum mcs_kind mode; - LListHead<GprsMs>& list() {return this->m_list;} - const LListHead<GprsMs>& list() const {return this->m_list;} - const LListHead<gprs_rlcmac_tbf>& old_tbfs() const {return m_old_tbfs;} + unsigned dl_ctrl_msg; +}; - void update_l1_meas(const pcu_l1_meas *meas); - const pcu_l1_meas* l1_meas() const {return &m_l1_meas;}; - unsigned nack_rate_dl() const; - unsigned dl_ctrl_msg() const; - void update_dl_ctrl_msg(); +struct GprsMs *ms_alloc(struct BTS *bts, uint32_t tlli); - /* internal use */ - static void timeout(void *priv_); +int ms_first_common_ts(const struct GprsMs *ms); +void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx, + uint8_t ul_slots, uint8_t dl_slots); +struct GprsMs *ms_ref(struct GprsMs *ms); +void ms_unref(struct GprsMs *ms); +void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode); +void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_); +void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_); +void ms_set_ta(struct GprsMs *ms, uint8_t ta_); - bool app_info_pending; +enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms); +enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms); +enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms); +void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme); -protected: - void merge_old_ms(GprsMs *old_ms); - void update_status(); - GprsMs *ref(); - void unref(); - void start_timer(); - void stop_timer(); - void update_cs_ul(const pcu_l1_meas*); - -private: - BTS *m_bts; - Callback * m_cb; - gprs_rlcmac_ul_tbf *m_ul_tbf; - gprs_rlcmac_dl_tbf *m_dl_tbf; - LListHead<gprs_rlcmac_tbf> m_old_tbfs; - - uint32_t m_tlli; - uint32_t m_new_ul_tlli; - uint32_t m_new_dl_tlli; +void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate); +uint8_t ms_current_pacch_slots(const struct GprsMs *ms); - /* store IMSI for look-up and PCH retransmission */ - char m_imsi[OSMO_IMSI_BUF_SIZE]; - uint8_t m_ta; - uint8_t m_ms_class; - uint8_t m_egprs_ms_class; - /* current coding scheme */ - enum CodingScheme m_current_cs_ul; - enum CodingScheme m_current_cs_dl; +void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms); - gprs_llc_queue m_llc_queue; +void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf); +void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf); - bool m_is_idle; - int m_ref; - LListHead<GprsMs> m_list; - struct osmo_timer_list m_timer; - unsigned m_delay; +void ms_set_tlli(struct GprsMs *ms, uint32_t tlli); +bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli); +void ms_set_imsi(struct GprsMs *ms, const char *imsi); - int64_t m_last_cs_not_low; +void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas); - pcu_l1_meas m_l1_meas; - unsigned m_nack_rate_dl; - uint8_t m_reserved_dl_slots; - uint8_t m_reserved_ul_slots; - gprs_rlcmac_trx *m_current_trx; +struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir); +static inline struct gprs_rlcmac_ul_tbf *ms_ul_tbf(const struct GprsMs *ms) {return ms->ul_tbf;} +static inline struct gprs_rlcmac_dl_tbf *ms_dl_tbf(const struct GprsMs *ms) {return ms->dl_tbf;} - struct gprs_codel *m_codel_state; - enum mcs_kind m_mode; - unsigned m_dl_ctrl_msg; -}; +void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb); -inline bool GprsMs::is_idle() const +static inline bool ms_is_idle(const struct GprsMs *ms) { - return !m_ul_tbf && !m_dl_tbf && !m_ref && llist_empty(&m_old_tbfs); + return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs); } -inline bool GprsMs::need_dl_tbf() const +static inline struct gprs_llc_queue *ms_llc_queue(struct GprsMs *ms) { - if (dl_tbf() != NULL && dl_tbf()->state_is_not(GPRS_RLCMAC_WAIT_RELEASE)) - return false; - - return llc_queue()->size() > 0; + return &ms->llc_queue; } -inline uint32_t GprsMs::tlli() const +static inline bool ms_need_dl_tbf(struct GprsMs *ms) { - if (m_new_ul_tlli != GSM_RESERVED_TMSI) - return m_new_ul_tlli; - if (m_tlli != GSM_RESERVED_TMSI) - return m_tlli; + if (ms_dl_tbf(ms) != NULL && + tbf_state((const struct gprs_rlcmac_tbf *)ms_dl_tbf(ms)) != GPRS_RLCMAC_WAIT_RELEASE) + return false; - return m_new_dl_tlli; + return llc_queue_size(ms_llc_queue(ms)) > 0; } -inline bool GprsMs::check_tlli(uint32_t tlli) +static inline uint32_t ms_tlli(const struct GprsMs *ms) { - return tlli != GSM_RESERVED_TMSI && - (tlli == m_tlli || tlli == m_new_ul_tlli || tlli == m_new_dl_tlli); -} + if (ms->new_ul_tlli != GSM_RESERVED_TMSI) + return ms->new_ul_tlli; + if (ms->tlli != GSM_RESERVED_TMSI) + return ms->tlli; -inline const char *GprsMs::imsi() const -{ - return m_imsi; + return ms->new_dl_tlli; } -inline uint8_t GprsMs::ta() const +static inline bool ms_check_tlli(struct GprsMs *ms, uint32_t tlli) { - return m_ta; + return tlli != GSM_RESERVED_TMSI && + (tlli == ms->tlli || tlli == ms->new_ul_tlli || tlli == ms->new_dl_tlli); } -inline uint8_t GprsMs::ms_class() const +static inline const char *ms_imsi(const struct GprsMs *ms) { - return m_ms_class; + return ms->imsi; } -inline uint8_t GprsMs::egprs_ms_class() const +static inline uint8_t ms_ta(const struct GprsMs *ms) { - return m_egprs_ms_class; + return ms->ta; } -inline enum CodingScheme GprsMs::current_cs_ul() const +static inline uint8_t ms_ms_class(const struct GprsMs *ms) { - return m_current_cs_ul; + return ms->ms_class; } -inline enum mcs_kind GprsMs::mode() const +static inline uint8_t ms_egprs_ms_class(const struct GprsMs *ms) { - return m_mode; + return ms->egprs_ms_class; } -inline void GprsMs::set_timeout(unsigned secs) +static inline enum CodingScheme ms_current_cs_ul(const struct GprsMs *ms) { - m_delay = secs; + return ms->current_cs_ul; } -inline gprs_llc_queue *GprsMs::llc_queue() +static inline enum mcs_kind ms_mode(const struct GprsMs *ms) { - return &m_llc_queue; + return ms->mode; } -inline const gprs_llc_queue *GprsMs::llc_queue() const +static inline void ms_set_timeout(struct GprsMs *ms, unsigned secs) { - return &m_llc_queue; + ms->delay = secs; } -inline gprs_codel *GprsMs::codel_state() const +static inline struct gprs_codel *ms_codel_state(const struct GprsMs *ms) { - return m_codel_state; + return ms->codel_state; } -inline unsigned GprsMs::nack_rate_dl() const +static inline unsigned ms_nack_rate_dl(const struct GprsMs *ms) { - return m_nack_rate_dl; + return ms->nack_rate_dl; } -inline unsigned GprsMs::dl_ctrl_msg() const +static inline unsigned ms_dl_ctrl_msg(const struct GprsMs *ms) { - return m_dl_ctrl_msg; + return ms->dl_ctrl_msg; } -inline void GprsMs::update_dl_ctrl_msg() +static inline void ms_update_dl_ctrl_msg(struct GprsMs *ms) { - m_dl_ctrl_msg++; + ms->dl_ctrl_msg++; } -inline uint8_t GprsMs::reserved_dl_slots() const +static inline uint8_t ms_reserved_dl_slots(const struct GprsMs *ms) { - return m_reserved_dl_slots; + return ms->reserved_dl_slots; } -inline uint8_t GprsMs::reserved_ul_slots() const +static inline uint8_t ms_reserved_ul_slots(const struct GprsMs *ms) { - return m_reserved_ul_slots; + return ms->reserved_ul_slots; } -inline gprs_rlcmac_trx *GprsMs::current_trx() const +static inline struct gprs_rlcmac_trx *ms_current_trx(const struct GprsMs *ms) { - return m_current_trx; + return ms->current_trx; } #define LOGPMS(ms, category, level, fmt, args...) \ LOGP(category, level, "MS(TLLI=0x%08x, IMSI=%s, TA=%" PRIu8 ", %" PRIu8 "/%" PRIu8 ",%s%s) " fmt, \ - (ms)->tlli(), (ms)->imsi(), (ms)->ta(), (ms)->ms_class(), (ms)->egprs_ms_class(), \ - (ms)->ul_tbf() ? " UL": "", \ - (ms)->dl_tbf() ? " DL": "", \ + ms_tlli(ms), ms_imsi(ms), ms_ta(ms), ms_ms_class(ms), ms_egprs_ms_class(ms), \ + ms_ul_tbf(ms) ? " UL": "", \ + ms_dl_tbf(ms) ? " DL": "", \ ## args) + +#ifdef __cplusplus +} +#endif diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp index 73570b3a..6d5b09ec 100644 --- a/src/gprs_ms_storage.cpp +++ b/src/gprs_ms_storage.cpp @@ -31,9 +31,29 @@ extern "C" { #define GPRS_UNDEFINED_IMSI "000" +static void ms_storage_ms_idle_cb(struct GprsMs *ms) +{ + llist_del(&ms->list); + if (ms->bts) + ms->bts->stat_item_add(STAT_MS_PRESENT, -1); + if (ms_is_idle(ms)) + talloc_free(ms); +} + +static void ms_storage_ms_active_cb(struct GprsMs *ms) +{ + /* Nothing to do */ +} + +static struct gpr_ms_callback ms_storage_ms_cb = { + .ms_idle = ms_storage_ms_idle_cb, + .ms_active = ms_storage_ms_active_cb, +}; + GprsMsStorage::GprsMsStorage(BTS *bts) : m_bts(bts) { + INIT_LLIST_HEAD(&m_list); } GprsMsStorage::~GprsMsStorage() @@ -43,40 +63,26 @@ GprsMsStorage::~GprsMsStorage() void GprsMsStorage::cleanup() { - LListHead<GprsMs> *pos, *tmp; + struct llist_head *pos, *tmp; llist_for_each_safe(pos, tmp, &m_list) { - GprsMs *ms = pos->entry(); - ms->set_callback(NULL); - ms_idle(ms); + struct GprsMs *ms = llist_entry(pos, typeof(*ms), list); + ms_set_callback(ms, NULL); + ms_storage_ms_idle_cb(ms); } } -void GprsMsStorage::ms_idle(class GprsMs *ms) -{ - llist_del(&ms->list()); - if (m_bts) - m_bts->stat_item_add(STAT_MS_PRESENT, -1); - if (ms->is_idle()) - delete ms; -} - -void GprsMsStorage::ms_active(class GprsMs *ms) -{ - /* Nothing to do */ -} - GprsMs *GprsMsStorage::get_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi) const { + struct llist_head *tmp; GprsMs *ms; - LListHead<GprsMs> *pos; if (tlli != GSM_RESERVED_TMSI || old_tlli != GSM_RESERVED_TMSI) { - llist_for_each(pos, &m_list) { - ms = pos->entry(); - if (ms->check_tlli(tlli)) + llist_for_each(tmp, &m_list) { + ms = llist_entry(tmp, typeof(*ms), list); + if (ms_check_tlli(ms, tlli)) return ms; - if (ms->check_tlli(old_tlli)) + if (ms_check_tlli(ms, old_tlli)) return ms; } } @@ -84,9 +90,9 @@ GprsMs *GprsMsStorage::get_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi /* not found by TLLI */ if (imsi && imsi[0] && strcmp(imsi, GPRS_UNDEFINED_IMSI) != 0) { - llist_for_each(pos, &m_list) { - ms = pos->entry(); - if (strcmp(imsi, ms->imsi()) == 0) + llist_for_each(tmp, &m_list) { + ms = llist_entry(tmp, typeof(*ms), list); + if (strcmp(imsi, ms_imsi(ms)) == 0) return ms; } } @@ -98,10 +104,10 @@ GprsMs *GprsMsStorage::create_ms() { GprsMs *ms; - ms = new GprsMs(m_bts, GSM_RESERVED_TMSI); + ms = ms_alloc(m_bts, GSM_RESERVED_TMSI); - ms->set_callback(this); - llist_add(&ms->list(), &m_list); + ms_set_callback(ms, &ms_storage_ms_cb); + llist_add(&ms->list, &m_list); if (m_bts) m_bts->stat_item_add(STAT_MS_PRESENT, 1); diff --git a/src/gprs_ms_storage.h b/src/gprs_ms_storage.h index 35062f3d..af496887 100644 --- a/src/gprs_ms_storage.h +++ b/src/gprs_ms_storage.h @@ -21,28 +21,24 @@ #pragma once #include "gprs_ms.h" -#include "cxx_linuxlist.h" #include "tbf.h" #include <stdint.h> #include <stddef.h> struct BTS; -class GprsMsStorage : public GprsMs::Callback { +class GprsMsStorage { public: GprsMsStorage(BTS *bts); ~GprsMsStorage(); void cleanup(); - virtual void ms_idle(class GprsMs *); - virtual void ms_active(class GprsMs *); - GprsMs *get_ms(uint32_t tlli, uint32_t old_tlli = GSM_RESERVED_TMSI, const char *imsi = NULL) const; GprsMs *create_ms(); - const LListHead<GprsMs>& ms_list() const {return m_list;} + const struct llist_head* ms_list() const {return &m_list;} private: BTS *m_bts; - LListHead<GprsMs> m_list; + struct llist_head m_list; /* list of struct GprsMs */ }; diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 70d82373..caf121f1 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -234,7 +234,7 @@ static struct msgb *sched_select_ctrl_msg( "message at RTS for %s (TRX=%d, TS=%d)\n", tbf_name(tbf), trx, ts); /* Updates the dl ctrl msg counter for ms */ - tbf->ms()->update_dl_ctrl_msg(); + ms_update_dl_ctrl_msg(tbf->ms()); return msg; } @@ -342,7 +342,7 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts, pdch->next_dl_tfi = (prio_tfi + 1) & 31; /* generate DL data block */ msg = prio_tbf->create_dl_acked_block(fn, ts, req_mcs_kind); - *is_egprs = prio_tbf->ms()->mode() != GPRS; + *is_egprs = ms_mode(prio_tbf->ms()) != GPRS; } return msg; @@ -463,7 +463,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, * only be able to read USF if dl block uses GMSK * (CS1-4, MCS1-4) */ - if (req_mcs_kind == EGPRS && usf_tbf->ms()->mode() != EGPRS) + if (req_mcs_kind == EGPRS && ms_mode(usf_tbf->ms()) != EGPRS) req_mcs_kind = EGPRS_GMSK; } else { usf = USF_UNUSED; diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 9551c598..1ef32f22 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -245,8 +245,8 @@ static int find_trx(const struct gprs_rlcmac_bts *bts_data, const GprsMs *ms, in unsigned ts; /* We must use the TRX currently actively used by an MS */ - if (ms && ms->current_trx()) - return ms->current_trx()->trx_no; + if (ms && ms_current_trx(ms)) + return ms_current_trx(ms)->trx_no; if (use_trx >= 0 && use_trx < 8) return use_trx; @@ -320,8 +320,8 @@ static int tfi_find_free(const BTS *bts, const gprs_rlcmac_trx *trx, const GprsM use_trx = trx->trx_no; } - if (use_trx == -1 && ms->current_trx()) - use_trx = ms->current_trx()->trx_no; + if (use_trx == -1 && ms_current_trx(ms)) + use_trx = ms_current_trx(ms)->trx_no; tfi = bts->tfi_find_free(dir, &trx_no, use_trx); if (tfi < 0) @@ -357,7 +357,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm const char *mask_reason = NULL; const GprsMs *ms = ms_; const gprs_rlcmac_tbf *tbf = tbf_; - gprs_rlcmac_trx *trx = ms->current_trx(); + gprs_rlcmac_trx *trx = ms_current_trx(ms); LOGPAL(tbf, "A", single, use_trx, LOGL_DEBUG, "Alloc start\n"); @@ -370,10 +370,10 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm if (!trx) trx = &bts->trx[trx_no]; - dl_slots = ms->reserved_dl_slots(); - ul_slots = ms->reserved_ul_slots(); + dl_slots = ms_reserved_dl_slots(ms); + ul_slots = ms_reserved_ul_slots(ms); - ts = ms->first_common_ts(); + ts = ms_first_common_ts(ms); if (ts >= 0) { mask_reason = "need to reuse TS"; @@ -420,7 +420,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm tbf_->trx = trx; /* the only one TS is the common TS */ tbf_->first_ts = tbf_->first_common_ts = ts; - ms_->set_reserved_slots(trx, 1 << ts, 1 << ts); + ms_set_reserved_slots(ms_, trx, 1 << ts, 1 << ts); tbf_->upgrade_to_multislot = 0; bts->bts->do_rate_ctr_inc(CTR_TBF_ALLOC_ALGO_A); @@ -774,11 +774,11 @@ static void update_ms_reserved_slots(gprs_rlcmac_trx *trx, GprsMs *ms, uint8_t r { char slot_info[9] = { 0 }; - if (res_ul_slots == ms->reserved_ul_slots() && res_dl_slots == ms->reserved_dl_slots()) + if (res_ul_slots == ms_reserved_ul_slots(ms) && res_dl_slots == ms_reserved_dl_slots(ms)) return; /* The reserved slots have changed, update the MS */ - ms->set_reserved_slots(trx, res_ul_slots, res_dl_slots); + ms_set_reserved_slots(ms, trx, res_ul_slots, res_dl_slots); ts_format(slot_info, dl_slots, ul_slots); LOGP(DRLCMAC, LOGL_DEBUG, "- Reserved DL/UL slots: (TS=0)\"%s\"(TS=7)\n", slot_info); @@ -867,10 +867,10 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm return -EINVAL; } - dl_slots = ms->reserved_dl_slots(); - ul_slots = ms->reserved_ul_slots(); - first_common_ts = ms->first_common_ts(); - trx = ms->current_trx(); + dl_slots = ms_reserved_dl_slots(ms); + ul_slots = ms_reserved_ul_slots(ms); + first_common_ts = ms_first_common_ts(ms); + trx = ms_current_trx(ms); /* Step 2a: Find usable TRX and TFI */ tfi = tfi_find_free(bts->bts, trx, ms, tbf->direction, use_trx, &trx_no); @@ -884,7 +884,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm trx = &bts->trx[trx_no]; if (!dl_slots || !ul_slots) { - rc = find_multi_slots(trx, ms->ms_class(), &ul_slots, &dl_slots); + rc = find_multi_slots(trx, ms_ms_class(ms), &ul_slots, &dl_slots); if (rc < 0) return rc; } diff --git a/src/llc.cpp b/src/llc.cpp index e2d01c29..d1122f5c 100644 --- a/src/llc.cpp +++ b/src/llc.cpp @@ -97,12 +97,12 @@ bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len) return true; } -void gprs_llc_queue::init() +void llc_queue_init(struct gprs_llc_queue *q) { - INIT_LLIST_HEAD(&m_queue); - m_queue_size = 0; - m_queue_octets = 0; - m_avg_queue_delay = 0; + INIT_LLIST_HEAD(&q->m_queue); + q->m_queue_size = 0; + q->m_queue_octets = 0; + q->m_avg_queue_delay = 0; } @@ -122,21 +122,21 @@ void gprs_llc_queue::enqueue(struct msgb *llc_msg, const struct timespec *expire msgb_enqueue(&m_queue, llc_msg); } -void gprs_llc_queue::clear(BTS *bts) +void llc_queue_clear(struct gprs_llc_queue *q, struct BTS *bts) { struct msgb *msg; - while ((msg = msgb_dequeue(&m_queue))) { + while ((msg = msgb_dequeue(&q->m_queue))) { if (bts) bts->do_rate_ctr_inc(CTR_LLC_FRAME_DROPPED); msgb_free(msg); } - m_queue_size = 0; - m_queue_octets = 0; + q->m_queue_size = 0; + q->m_queue_octets = 0; } -void gprs_llc_queue::move_and_merge(gprs_llc_queue *o) +void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o) { struct msgb *msg, *msg1 = NULL, *msg2 = NULL; struct llist_head new_queue; @@ -146,7 +146,7 @@ void gprs_llc_queue::move_and_merge(gprs_llc_queue *o) while (1) { if (msg1 == NULL) - msg1 = msgb_dequeue(&m_queue); + msg1 = msgb_dequeue(&q->m_queue); if (msg2 == NULL) msg2 = msgb_dequeue(&o->m_queue); @@ -178,15 +178,15 @@ void gprs_llc_queue::move_and_merge(gprs_llc_queue *o) queue_octets += msgb_length(msg); } - OSMO_ASSERT(llist_empty(&m_queue)); + OSMO_ASSERT(llist_empty(&q->m_queue)); OSMO_ASSERT(llist_empty(&o->m_queue)); o->m_queue_size = 0; o->m_queue_octets = 0; - llist_splice_init(&new_queue, &m_queue); - m_queue_size = queue_size; - m_queue_octets = queue_octets; + llist_splice_init(&new_queue, &q->m_queue); + q->m_queue_size = queue_size; + q->m_queue_octets = queue_octets; } #define ALPHA 0.5f @@ -18,9 +18,13 @@ #pragma once +#ifdef __cplusplus extern "C" { +#endif #include <osmocom/core/linuxlist.h> +#ifdef __cplusplus } +#endif #include <stdint.h> #include <string.h> @@ -34,6 +38,8 @@ struct BTS; * I represent the LLC data to a MS */ struct gprs_llc { + +#ifdef __cplusplus static bool is_user_data_frame(uint8_t *data, size_t len); void init(); @@ -43,92 +49,86 @@ struct gprs_llc { void put_frame(const uint8_t *data, size_t len); void put_dummy_frame(size_t req_len); void append_frame(const uint8_t *data, size_t len); - - void consume(size_t len); - void consume(uint8_t *data, size_t len); - - uint16_t chunk_size() const; - uint16_t remaining_space() const; - uint16_t frame_length() const; - - bool fits_in_current_frame(uint8_t size) const; +#endif uint8_t frame[LLC_MAX_LEN]; /* current DL or UL frame */ uint16_t m_index; /* current write/read position of frame */ uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */ }; +struct MetaInfo { + struct timespec recv_time; + struct timespec expire_time; +}; /** * I store the LLC frames that come from the SGSN. */ struct gprs_llc_queue { - struct MetaInfo { - struct timespec recv_time; - struct timespec expire_time; - }; - +#ifdef __cplusplus static void calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timespec *tv); static bool is_frame_expired(const struct timespec *now, const struct timespec *tv); static bool is_user_data_frame(uint8_t *data, size_t len); - void init(); - void enqueue(struct msgb *llc_msg, const struct timespec *expire_time); struct msgb *dequeue(const MetaInfo **info = 0); - void clear(BTS *bts); - void move_and_merge(gprs_llc_queue *o); - size_t size() const; - size_t octets() const; - -private: +#endif uint32_t m_avg_queue_delay; /* Average delay of data going through the queue */ size_t m_queue_size; size_t m_queue_octets; struct llist_head m_queue; /* queued LLC DL data */ - }; +#ifdef __cplusplus +extern "C" { +#endif +void llc_queue_init(struct gprs_llc_queue *q); +void llc_queue_clear(struct gprs_llc_queue *q, struct BTS *bts); +void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o); -inline uint16_t gprs_llc::chunk_size() const +static inline uint16_t llc_chunk_size(const struct gprs_llc *llc) { - return m_length - m_index; + return llc->m_length - llc->m_index; } -inline uint16_t gprs_llc::remaining_space() const +static inline uint16_t llc_remaining_space(const struct gprs_llc *llc) { - return LLC_MAX_LEN - m_length; + return LLC_MAX_LEN - llc->m_length; } -inline uint16_t gprs_llc::frame_length() const +static inline uint16_t llc_frame_length(const struct gprs_llc *llc) { - return m_length; + return llc->m_length; } -inline void gprs_llc::consume(size_t len) +static inline void llc_consume(struct gprs_llc *llc, size_t len) { - m_index += len; + llc->m_index += len; } -inline void gprs_llc::consume(uint8_t *data, size_t len) +static inline void llc_consume_data(struct gprs_llc *llc, uint8_t *data, size_t len) { /* copy and increment index */ - memcpy(data, frame + m_index, len); - consume(len); + memcpy(data, llc->frame + llc->m_index, len); + llc_consume(llc, len); } -inline bool gprs_llc::fits_in_current_frame(uint8_t chunk_size) const +static inline bool llc_fits_in_current_frame(const struct gprs_llc *llc, uint8_t chunk_size) { - return m_length + chunk_size <= LLC_MAX_LEN; + return llc->m_length + chunk_size <= LLC_MAX_LEN; } -inline size_t gprs_llc_queue::size() const +static inline size_t llc_queue_size(const struct gprs_llc_queue *q) { - return m_queue_size; + return q->m_queue_size; } -inline size_t gprs_llc_queue::octets() const +static inline size_t llc_queue_octets(const struct gprs_llc_queue *q) { - return m_queue_octets; + return q->m_queue_octets; +} + +#ifdef __cplusplus } +#endif diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index a9845916..9cc62708 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -318,7 +318,7 @@ static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind) struct gprs_rlcmac_bts *bts = bts_main_data(); int rc; int current_fn = get_current_fn(); - pcu_l1_meas meas; + struct pcu_l1_meas meas = {0}; uint8_t gsmtap_chantype; LOGP(DL1IF, LOGL_DEBUG, "Data indication received: sapi=%d arfcn=%d " @@ -328,11 +328,11 @@ static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind) switch (data_ind->sapi) { case PCU_IF_SAPI_PDTCH: - meas.set_rssi(data_ind->rssi); + pcu_l1_meas_set_rssi(&meas, data_ind->rssi); /* convert BER to % value */ - meas.set_ber(data_ind->ber10k / 100); - meas.set_bto(data_ind->ta_offs_qbits); - meas.set_link_qual(data_ind->lqual_cb / 10); + pcu_l1_meas_set_ber(&meas, data_ind->ber10k / 100); + pcu_l1_meas_set_bto(&meas, data_ind->ta_offs_qbits); + pcu_l1_meas_set_link_qual(&meas, data_ind->lqual_cb / 10); LOGP(DL1IF, LOGL_DEBUG, "Data indication with raw measurements received: BER10k = %d, BTO = %d, Q = %d\n", data_ind->ber10k, data_ind->ta_offs_qbits, data_ind->lqual_cb); @@ -824,8 +824,8 @@ static int pcu_rx_susp_req(struct gsm_pcu_if_susp_req *susp_req) if ((ms = bts->ms_store().get_ms(susp_req->tlli))) { /* We need to catch both pointers here since MS may become freed after first tbf_free(dl_tbf) if only DL TBF was available */ - dl_tbf = ms->dl_tbf(); - ul_tbf = ms->ul_tbf(); + dl_tbf = ms_dl_tbf(ms); + ul_tbf = ms_ul_tbf(ms); if (dl_tbf) tbf_free(dl_tbf); if (ul_tbf) @@ -840,7 +840,7 @@ static int pcu_rx_susp_req(struct gsm_pcu_if_susp_req *susp_req) static int pcu_rx_app_info_req(struct gsm_pcu_if_app_info_req *app_info_req) { - LListHead<GprsMs> *ms_iter; + GprsMs *ms; BTS *bts = BTS::main_bts(); struct gprs_rlcmac_bts *bts_data = bts->bts_data(); @@ -848,9 +848,8 @@ static int pcu_rx_app_info_req(struct gsm_pcu_if_app_info_req *app_info_req) app_info_req->application_type, app_info_req->len); bts_data->app_info_pending = 0; - llist_for_each(ms_iter, &bts->ms_store().ms_list()) { - GprsMs *ms = ms_iter->entry(); - if (!ms->dl_tbf()) + llist_for_each_entry(ms, bts->ms_store().ms_list(), list) { + if (!ms_dl_tbf(ms)) continue; bts_data->app_info_pending++; ms->app_info_pending = true; diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index f86e7085..65fea9c5 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -79,19 +79,13 @@ struct pcu_l1_meas_ts { unsigned have_ms_i_level:1; int16_t ms_i_level; /* I_LEVEL in dB */ - -#ifdef __cplusplus - pcu_l1_meas_ts& set_ms_i_level(int16_t v) { - ms_i_level = v; have_ms_i_level = 1; return *this; - } - - pcu_l1_meas_ts() : - have_ms_i_level(0), - ms_i_level(0) - {} -#endif }; +static inline void pcu_l1_meas_ts_set_ms_i_level(struct pcu_l1_meas_ts* ts, int16_t v) { + ts->ms_i_level = v; + ts->have_ms_i_level = 1; +} + struct pcu_l1_meas { unsigned have_rssi:1; unsigned have_ber:1; @@ -111,48 +105,43 @@ struct pcu_l1_meas { int16_t ms_sign_var; /* SIGN_VAR in dB */ struct pcu_l1_meas_ts ts[8]; - -#ifdef __cplusplus - pcu_l1_meas& set_rssi(int8_t v) { rssi = v; have_rssi = 1; return *this;} - pcu_l1_meas& set_ber(uint8_t v) { ber = v; have_ber = 1; return *this;} - pcu_l1_meas& set_bto(int16_t v) { bto = v; have_bto = 1; return *this;} - pcu_l1_meas& set_link_qual(int16_t v) { - link_qual = v; have_link_qual = 1; return *this; - } - pcu_l1_meas& set_ms_rx_qual(int16_t v) { - ms_rx_qual = v; have_ms_rx_qual = 1; return *this; - } - pcu_l1_meas& set_ms_c_value(int16_t v) { - ms_c_value = v; have_ms_c_value = 1; return *this; - } - pcu_l1_meas& set_ms_sign_var(int16_t v) { - ms_sign_var = v; have_ms_sign_var = 1; return *this; - } - pcu_l1_meas& set_ms_i_level(size_t idx, int16_t v) { - ts[idx].set_ms_i_level(v); have_ms_i_level = 1; return *this; - } - pcu_l1_meas() : - have_rssi(0), - have_ber(0), - have_bto(0), - have_link_qual(0), - have_ms_rx_qual(0), - have_ms_c_value(0), - have_ms_sign_var(0), - have_ms_i_level(0), - rssi(0), - ber(0), - bto(0), - link_qual(0), - ms_rx_qual(0), - ms_c_value(0), - ms_sign_var(0) - {} -#endif }; +static inline void pcu_l1_meas_set_rssi(struct pcu_l1_meas *m, int8_t v) { + m->rssi = v; + m->have_rssi = 1; +} +static inline void pcu_l1_meas_set_ber(struct pcu_l1_meas *m, uint8_t v) { + m->ber = v; + m->have_ber = 1; +} +static inline void pcu_l1_meas_set_bto(struct pcu_l1_meas *m, int16_t v) { + m->bto = v; + m->have_bto = 1; +} +static inline void pcu_l1_meas_set_link_qual(struct pcu_l1_meas *m, int16_t v) { + m->link_qual = v; + m->have_link_qual = 1; +} +static inline void pcu_l1_meas_set_ms_rx_qual(struct pcu_l1_meas *m, int16_t v) { + m->ms_rx_qual = v; + m->have_ms_rx_qual = 1; +} +static inline void pcu_l1_meas_set_ms_c_value(struct pcu_l1_meas *m, int16_t v) { + m->ms_c_value = v; + m->have_ms_c_value = 1; +} +static inline void pcu_l1_meas_set_ms_sign_var(struct pcu_l1_meas *m, int16_t v) { + m->ms_sign_var = v; + m->have_ms_sign_var = 1; +} +static inline void pcu_l1_meas_set_ms_i_level(struct pcu_l1_meas *m, size_t idx, int16_t v) { + pcu_l1_meas_ts_set_ms_i_level(&m->ts[idx], v); + m->have_ms_i_level = 1; +} + #ifdef __cplusplus -void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, +void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, uint32_t fn, uint8_t block_nr); void pcu_l1if_tx_ptcch(uint8_t trx, uint8_t ts, uint16_t arfcn, uint32_t fn, uint8_t block_nr, diff --git a/src/pcu_utils.h b/src/pcu_utils.h index 8196a93f..cb2fd91a 100644 --- a/src/pcu_utils.h +++ b/src/pcu_utils.h @@ -15,26 +15,32 @@ * 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 +#ifdef __cplusplus extern "C" { +#endif #include <osmocom/gsm/gsm_utils.h> +#ifdef __cplusplus } +#endif + #include <time.h> -inline int msecs_to_frames(int msecs) { +static inline int msecs_to_frames(int msecs) { return (msecs * (1024 * 1000 / 4615)) / 1024; } -inline uint32_t next_fn(uint32_t fn, uint32_t offset) +static inline uint32_t next_fn(uint32_t fn, uint32_t offset) { return (fn + offset) % GSM_MAX_FN; } -inline void csecs_to_timespec(unsigned csecs, struct timespec *ts) { +static inline void csecs_to_timespec(unsigned csecs, struct timespec *ts) { ts->tv_sec = csecs / 100; ts->tv_nsec = (csecs % 100) * 10000000; } +#ifdef __cplusplus template <typename T> inline unsigned int pcu_bitcount(T x) { @@ -44,8 +50,15 @@ inline unsigned int pcu_bitcount(T x) return count; } +#endif -inline uint8_t pcu_lsb(uint8_t x) +static inline uint8_t pcu_lsb(uint8_t x) { return x & -x; } + +/* Used to store a C++ class in a llist used by C code */ +struct llist_item { + struct llist_head list; /* item used by llist */ + void *entry; +}; diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp index 416c006b..6100b136 100644 --- a/src/pcu_vty_functions.cpp +++ b/src/pcu_vty_functions.cpp @@ -61,7 +61,7 @@ static void tbf_print_vty_info(struct vty *vty, gprs_rlcmac_tbf *tbf) tbf->first_ts, tbf->first_common_ts, tbf->control_ts, tbf->ms_class(), - tbf->ms() ? tbf->ms()->egprs_ms_class() : -1, + tbf->ms() ? ms_egprs_ms_class(tbf->ms()) : -1, VTY_NEWLINE); vty_out(vty, " TS_alloc="); for (int i = 0; i < 8; i++) { @@ -79,7 +79,7 @@ static void tbf_print_vty_info(struct vty *vty, gprs_rlcmac_tbf *tbf) ul_tbf->window_size(), win->v_q(), win->v_r()); vty_out(vty, "%s", VTY_NEWLINE); vty_out(vty, " TBF Statistics:%s", VTY_NEWLINE); - if (GPRS == tbf->ms()->mode()) { + if (GPRS == ms_mode(tbf->ms())) { vty_out_rate_ctr_group(vty, " ", ul_tbf->m_ul_gprs_ctrs); } else { vty_out_rate_ctr_group(vty, " ", ul_tbf->m_ul_egprs_ctrs); @@ -92,7 +92,7 @@ static void tbf_print_vty_info(struct vty *vty, gprs_rlcmac_tbf *tbf) win->window_stalled() ? " STALLED" : ""); vty_out(vty, "%s", VTY_NEWLINE); vty_out_rate_ctr_group(vty, " ", tbf->m_ctrs); - if (GPRS == tbf->ms()->mode()) { + if (GPRS == ms_mode(tbf->ms())) { vty_out_rate_ctr_group(vty, " ", dl_tbf->m_dl_gprs_ctrs); } else { vty_out_rate_ctr_group(vty, " ", dl_tbf->m_dl_egprs_ctrs); @@ -124,81 +124,83 @@ int pcu_vty_show_tbf_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data, uint static int show_ms(struct vty *vty, GprsMs *ms) { unsigned i; - LListHead<gprs_rlcmac_tbf> *i_tbf; + struct llist_item *i_tbf; uint8_t slots; - vty_out(vty, "MS TLLI=%08x, IMSI=%s%s", ms->tlli(), ms->imsi(), VTY_NEWLINE); - vty_out(vty, " Timing advance (TA): %d%s", ms->ta(), VTY_NEWLINE); - vty_out(vty, " Coding scheme uplink: %s%s", mcs_name(ms->current_cs_ul()), + vty_out(vty, "MS TLLI=%08x, IMSI=%s%s", ms_tlli(ms), ms_imsi(ms), VTY_NEWLINE); + vty_out(vty, " Timing advance (TA): %d%s", ms_ta(ms), VTY_NEWLINE); + vty_out(vty, " Coding scheme uplink: %s%s", mcs_name(ms_current_cs_ul(ms)), VTY_NEWLINE); - vty_out(vty, " Coding scheme downlink: %s%s", mcs_name(ms->current_cs_dl()), + vty_out(vty, " Coding scheme downlink: %s%s", mcs_name(ms_current_cs_dl(ms)), VTY_NEWLINE); - vty_out(vty, " Mode: %s%s", mode_name(ms->mode()), VTY_NEWLINE); - vty_out(vty, " MS class: %d%s", ms->ms_class(), VTY_NEWLINE); - vty_out(vty, " EGPRS MS class: %d%s", ms->egprs_ms_class(), VTY_NEWLINE); + vty_out(vty, " Mode: %s%s", mode_name(ms_mode(ms)), VTY_NEWLINE); + vty_out(vty, " MS class: %d%s", ms_ms_class(ms), VTY_NEWLINE); + vty_out(vty, " EGPRS MS class: %d%s", ms_egprs_ms_class(ms), VTY_NEWLINE); vty_out(vty, " PACCH: "); - slots = ms->current_pacch_slots(); + slots = ms_current_pacch_slots(ms); for (int i = 0; i < 8; i++) if (slots & (1 << i)) vty_out(vty, "%d ", i); vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, " LLC queue length: %zd%s", ms->llc_queue()->size(), + vty_out(vty, " LLC queue length: %zd%s", llc_queue_size(ms_llc_queue(ms)), VTY_NEWLINE); - vty_out(vty, " LLC queue octets: %zd%s", ms->llc_queue()->octets(), + vty_out(vty, " LLC queue octets: %zd%s", llc_queue_octets(ms_llc_queue(ms)), VTY_NEWLINE); - if (ms->l1_meas()->have_rssi) + if (ms->l1_meas.have_rssi) vty_out(vty, " RSSI: %d dBm%s", - ms->l1_meas()->rssi, VTY_NEWLINE); - if (ms->l1_meas()->have_ber) + ms->l1_meas.rssi, VTY_NEWLINE); + if (ms->l1_meas.have_ber) vty_out(vty, " Bit error rate: %d %%%s", - ms->l1_meas()->ber, VTY_NEWLINE); - if (ms->l1_meas()->have_link_qual) + ms->l1_meas.ber, VTY_NEWLINE); + if (ms->l1_meas.have_link_qual) vty_out(vty, " Link quality: %d dB%s", - ms->l1_meas()->link_qual, VTY_NEWLINE); - if (ms->l1_meas()->have_bto) + ms->l1_meas.link_qual, VTY_NEWLINE); + if (ms->l1_meas.have_bto) vty_out(vty, " Burst timing offset: %d/4 bit%s", - ms->l1_meas()->bto, VTY_NEWLINE); - if (ms->l1_meas()->have_ms_rx_qual) + ms->l1_meas.bto, VTY_NEWLINE); + if (ms->l1_meas.have_ms_rx_qual) vty_out(vty, " Downlink NACK rate: %d %%%s", - ms->nack_rate_dl(), VTY_NEWLINE); - if (ms->l1_meas()->have_ms_rx_qual) + ms_nack_rate_dl(ms), VTY_NEWLINE); + if (ms->l1_meas.have_ms_rx_qual) vty_out(vty, " MS RX quality: %d %%%s", - ms->l1_meas()->ms_rx_qual, VTY_NEWLINE); - if (ms->l1_meas()->have_ms_c_value) + ms->l1_meas.ms_rx_qual, VTY_NEWLINE); + if (ms->l1_meas.have_ms_c_value) vty_out(vty, " MS C value: %d dB%s", - ms->l1_meas()->ms_c_value, VTY_NEWLINE); - if (ms->l1_meas()->have_ms_sign_var) + ms->l1_meas.ms_c_value, VTY_NEWLINE); + if (ms->l1_meas.have_ms_sign_var) vty_out(vty, " MS SIGN variance: %d dB%s", - ms->l1_meas()->ms_sign_var, VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(ms->l1_meas()->ts); ++i) { - if (ms->l1_meas()->ts[i].have_ms_i_level) + ms->l1_meas.ms_sign_var, VTY_NEWLINE); + for (i = 0; i < ARRAY_SIZE(ms->l1_meas.ts); ++i) { + if (ms->l1_meas.ts[i].have_ms_i_level) vty_out(vty, " MS I level (slot %d): %d dB%s", - i, ms->l1_meas()->ts[i].ms_i_level, VTY_NEWLINE); + i, ms->l1_meas.ts[i].ms_i_level, VTY_NEWLINE); } - vty_out(vty, " RLC/MAC DL Control Msg: %d%s", ms->dl_ctrl_msg(), + vty_out(vty, " RLC/MAC DL Control Msg: %d%s", ms_dl_ctrl_msg(ms), VTY_NEWLINE); - if (ms->ul_tbf()) + if (ms_ul_tbf(ms)) vty_out(vty, " Uplink TBF: TFI=%d, state=%s%s", - ms->ul_tbf()->tfi(), - ms->ul_tbf()->state_name(), + ms_ul_tbf(ms)->tfi(), + ms_ul_tbf(ms)->state_name(), VTY_NEWLINE); - if (ms->dl_tbf()) { + if (ms_dl_tbf(ms)) { vty_out(vty, " Downlink TBF: TFI=%d, state=%s%s", - ms->dl_tbf()->tfi(), - ms->dl_tbf()->state_name(), + ms_dl_tbf(ms)->tfi(), + ms_dl_tbf(ms)->state_name(), VTY_NEWLINE); vty_out(vty, " Current DL Throughput: %d Kbps %s", - ms->dl_tbf()->m_bw.dl_throughput, + ms_dl_tbf(ms)->m_bw.dl_throughput, VTY_NEWLINE); } - llist_for_each(i_tbf, &ms->old_tbfs()) + llist_for_each_entry(i_tbf, &ms->old_tbfs, list) { + struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)i_tbf->entry; vty_out(vty, " Old %-19s TFI=%d, state=%s%s", - i_tbf->entry()->direction == GPRS_RLCMAC_UL_TBF ? + tbf_direction(tbf) == GPRS_RLCMAC_UL_TBF ? "Uplink TBF:" : "Downlink TBF:", - i_tbf->entry()->tfi(), - i_tbf->entry()->state_name(), + tbf->tfi(), + tbf->state_name(), VTY_NEWLINE); + } return CMD_SUCCESS; } @@ -206,10 +208,10 @@ static int show_ms(struct vty *vty, GprsMs *ms) int pcu_vty_show_ms_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data) { BTS *bts = bts_data->bts; - LListHead<GprsMs> *ms_iter; + GprsMs *ms_iter; - llist_for_each(ms_iter, &bts->ms_store().ms_list()) - show_ms(vty, ms_iter->entry()); + llist_for_each_entry(ms_iter, bts->ms_store().ms_list(), list) + show_ms(vty, ms_iter); return CMD_SUCCESS; } diff --git a/src/pdch.cpp b/src/pdch.cpp index 4a0ff068..49cce8d3 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -68,9 +68,9 @@ static void get_rx_qual_meas(struct pcu_l1_meas *meas, uint8_t rx_qual_enc) 18, /* 18,10 % */ }; - meas->set_ms_rx_qual(rx_qual_map[ - OSMO_MIN(rx_qual_enc, ARRAY_SIZE(rx_qual_map)-1) - ]); + pcu_l1_meas_set_ms_rx_qual(meas, rx_qual_map[ + OSMO_MIN(rx_qual_enc, ARRAY_SIZE(rx_qual_map)-1) + ]); } static void get_meas(struct pcu_l1_meas *meas, @@ -78,9 +78,9 @@ static void get_meas(struct pcu_l1_meas *meas, { unsigned i; - meas->set_ms_c_value(qr->C_VALUE); + pcu_l1_meas_set_ms_c_value(meas, qr->C_VALUE); if (qr->Exist_SIGN_VAR) - meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */ + pcu_l1_meas_set_ms_sign_var(meas, (qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */ for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->I_LEVEL_TN), ARRAY_SIZE(meas->ts)); i++) { @@ -88,7 +88,7 @@ static void get_meas(struct pcu_l1_meas *meas, LOGP(DRLCMAC, LOGL_INFO, "Packet resource request: i_level[%d] = %d\n", i, qr->I_LEVEL_TN[i].I_LEVEL); - meas->set_ms_i_level(i, -2 * qr->I_LEVEL_TN[i].I_LEVEL); + pcu_l1_meas_set_ms_i_level(meas, i, -2 * qr->I_LEVEL_TN[i].I_LEVEL); } } } @@ -99,8 +99,8 @@ static void get_meas(struct pcu_l1_meas *meas, unsigned i; get_rx_qual_meas(meas, qr->RXQUAL); - meas->set_ms_c_value(qr->C_VALUE); - meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */ + pcu_l1_meas_set_ms_c_value(meas, qr->C_VALUE); + pcu_l1_meas_set_ms_sign_var(meas, (qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */ for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->Slot), ARRAY_SIZE(meas->ts)); i++) { @@ -108,7 +108,7 @@ static void get_meas(struct pcu_l1_meas *meas, LOGP(DRLCMAC, LOGL_DEBUG, "Channel quality report: i_level[%d] = %d\n", i, qr->Slot[i].I_LEVEL_TN); - meas->set_ms_i_level(i, -2 * qr->Slot[i].I_LEVEL_TN); + pcu_l1_meas_set_ms_i_level(meas, i, -2 * qr->Slot[i].I_LEVEL_TN); } } } @@ -307,11 +307,11 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with " "unknown TBF corresponds to MS with IMSI %s, TA %d, " "uTBF (TFI=%d, state=%s), dTBF (TFI=%d, state=%s)\n", - ms->imsi(), ms->ta(), - ms->ul_tbf() ? ms->ul_tbf()->tfi() : 0, - ms->ul_tbf() ? ms->ul_tbf()->state_name() : "None", - ms->dl_tbf() ? ms->dl_tbf()->tfi() : 0, - ms->dl_tbf() ? ms->dl_tbf()->state_name() : "None"); + ms_imsi(ms), ms_ta(ms), + ms_ul_tbf(ms) ? ms_ul_tbf(ms)->tfi() : 0, + ms_ul_tbf(ms) ? ms_ul_tbf(ms)->state_name() : "None", + ms_dl_tbf(ms) ? ms_dl_tbf(ms)->tfi() : 0, + ms_dl_tbf(ms) ? ms_dl_tbf(ms)->state_name() : "None"); return; } @@ -339,7 +339,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, tbf->n_reset(N3105); TBF_SET_ASS_STATE_DL(tbf, GPRS_RLCMAC_DL_ASS_NONE); - new_tbf = tbf->ms() ? tbf->ms()->dl_tbf() : NULL; + new_tbf = tbf->ms() ? ms_dl_tbf(tbf->ms()) : NULL; if (!new_tbf) { LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL " "TBF is gone TLLI=0x%08x\n", tlli); @@ -371,7 +371,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, tbf->n_reset(N3105); TBF_SET_ASS_STATE_UL(tbf, GPRS_RLCMAC_UL_ASS_NONE); - new_tbf = tbf->ms() ? tbf->ms()->ul_tbf() : NULL; + new_tbf = tbf->ms() ? ms_ul_tbf(tbf->ms()) : NULL; if (!new_tbf) { LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL " "TBF is gone TLLI=0x%08x\n", tlli); @@ -389,7 +389,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, /* there might be LLC packets waiting in the queue, but the DL * TBF might have been released while the UL TBF has been * established */ - if (new_tbf->ms()->need_dl_tbf()) + if (ms_need_dl_tbf(new_tbf->ms())) new_tbf->establish_dl_tbf_on_pacch(); return; @@ -460,7 +460,7 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n /* get measurements */ if (tbf->ms()) { get_meas(meas, &ack_nack->Channel_Quality_Report); - tbf->ms()->update_l1_meas(meas); + ms_update_l1_meas(tbf->ms(), meas); } } @@ -570,19 +570,19 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, if (!ms) { ms_found = false; ms = bts()->ms_alloc(0, 0); /* ms class updated later */ - ms->set_tlli(tlli); + ms_set_tlli(ms, tlli); } - ul_tbf = ms->ul_tbf(); /* hence ul_tbf may be NULL */ + ul_tbf = ms_ul_tbf(ms); /* hence ul_tbf may be NULL */ /* Keep the ms, even if it gets idle temporarily */ - GprsMs::Guard guard(ms); + ms_ref(ms); LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF " "in packet resource request of single " "block, so we provide one:\n"); sba = bts()->sba()->find(this, fn); if (sba) { - ms->set_ta(sba->ta); + ms_set_ta(ms, sba->ta); bts()->sba()->free_sba(sba); } else if (!ul_tbf || !ul_tbf->state_is(GPRS_RLCMAC_FINISHED)) { LOGPTBFUL(ul_tbf, LOGL_NOTICE, @@ -599,9 +599,9 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, ms_class = Decoding::get_ms_class_by_capability(&request->MS_Radio_Access_capability2); egprs_ms_class = Decoding::get_egprs_ms_class_by_capability(&request->MS_Radio_Access_capability2); if (ms_class) - ms->set_ms_class(ms_class); + ms_set_ms_class(ms, ms_class); if (egprs_ms_class) - ms->set_egprs_ms_class(egprs_ms_class); + ms_set_egprs_ms_class(ms, egprs_ms_class); } /* Get rid of previous finished UL TBF before providing a new one */ @@ -616,7 +616,7 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, if (!ul_tbf) { handle_tbf_reject(bts_data(), ms, tlli, trx_no(), ts_no); - return; + goto return_unref; } /* set control ts to current MS's TS, until assignment complete */ @@ -630,8 +630,10 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, /* get measurements */ if (ul_tbf->ms()) { get_meas(meas, request); - ul_tbf->ms()->update_l1_meas(meas); + ms_update_l1_meas(ul_tbf->ms(), meas); } +return_unref: + ms_unref(ms); return; } @@ -674,10 +676,10 @@ void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *repor LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement " "but TLLI 0x%08x is unknown\n", report->TLLI); ms = bts()->ms_alloc(0, 0); - ms->set_tlli(report->TLLI); + ms_set_tlli(ms, report->TLLI); } if ((sba = bts()->sba()->find(this, fn))) { - ms->set_ta(sba->ta); + ms_set_ta(ms, sba->ta); bts()->sba()->free_sba(sba); } gprs_rlcmac_meas_rep(ms, report); diff --git a/src/tbf.cpp b/src/tbf.cpp index e92dfb64..fde44ba3 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -141,14 +141,13 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_directio m_tfi(0), m_created_ts(0), m_ctrs(NULL), - m_ms(ms), state(GPRS_RLCMAC_NULL), + m_ms(ms), dl_ass_state(GPRS_RLCMAC_DL_ASS_NONE), ul_ass_state(GPRS_RLCMAC_UL_ASS_NONE), ul_ack_state(GPRS_RLCMAC_UL_ACK_NONE), poll_state(GPRS_RLCMAC_POLL_NONE), m_list(this), - m_ms_list(this), m_egprs_enabled(false) { /* The classes of these members do not have proper constructors yet. @@ -158,6 +157,9 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_directio memset(&Narr, 0, sizeof(Narr)); memset(&gsm_timer, 0, sizeof(gsm_timer)); + memset(&m_ms_list, 0, sizeof(m_ms_list)); + m_ms_list.entry = this; + m_rlc.init(); m_llc.init(); @@ -171,27 +173,27 @@ gprs_rlcmac_bts *gprs_rlcmac_tbf::bts_data() const uint32_t gprs_rlcmac_tbf::tlli() const { - return m_ms ? m_ms->tlli() : GSM_RESERVED_TMSI; + return m_ms ? ms_tlli(m_ms) : GSM_RESERVED_TMSI; } const char *gprs_rlcmac_tbf::imsi() const { - return m_ms->imsi(); + return ms_imsi(m_ms); } uint8_t gprs_rlcmac_tbf::ta() const { - return m_ms->ta(); + return ms_ta(m_ms); } void gprs_rlcmac_tbf::set_ta(uint8_t ta) { - ms()->set_ta(ta); + ms_set_ta(m_ms, ta); } uint8_t gprs_rlcmac_tbf::ms_class() const { - return m_ms->ms_class(); + return ms_ms_class(m_ms); } enum CodingScheme gprs_rlcmac_tbf::current_cs() const @@ -199,28 +201,21 @@ enum CodingScheme gprs_rlcmac_tbf::current_cs() const enum CodingScheme cs; if (direction == GPRS_RLCMAC_UL_TBF) - cs = m_ms ? m_ms->current_cs_ul() : UNKNOWN; + cs = m_ms ? ms_current_cs_ul(m_ms) : UNKNOWN; else - cs = m_ms ? m_ms->current_cs_dl() : UNKNOWN; + cs = m_ms ? ms_current_cs_dl(m_ms) : UNKNOWN; return cs; } gprs_llc_queue *gprs_rlcmac_tbf::llc_queue() { - return m_ms ? m_ms->llc_queue() : NULL; + return m_ms ? ms_llc_queue(m_ms) : NULL; } const gprs_llc_queue *gprs_rlcmac_tbf::llc_queue() const { - return m_ms ? m_ms->llc_queue() : NULL; -} - -size_t gprs_rlcmac_tbf::llc_queue_size() const -{ - /* m_ms->llc_queue() never returns NULL: GprsMs::m_llc_queue is a - * member instance. */ - return m_ms ? m_ms->llc_queue()->size() : 0; + return ms_llc_queue(m_ms); } void gprs_rlcmac_tbf::set_ms(GprsMs *ms) @@ -229,13 +224,13 @@ void gprs_rlcmac_tbf::set_ms(GprsMs *ms) return; if (m_ms) { - m_ms->detach_tbf(this); + ms_detach_tbf(m_ms, this); } m_ms = ms; if (m_ms) - m_ms->attach_tbf(this); + ms_attach_tbf(m_ms, this); } void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir) @@ -247,18 +242,18 @@ void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction di * MS object that belongs to that TLLI and if yes make sure one of them * gets deleted. This is the same problem that can arise with * IMSI in gprs_rlcmac_dl_tbf::handle() so there should be a unified solution */ - if (!ms()->check_tlli(tlli)) { + if (!ms_check_tlli(ms(), tlli)) { GprsMs *old_ms; old_ms = bts->ms_store().get_ms(tlli, 0, NULL); if (old_ms) - ms()->merge_and_clear_ms(old_ms); + ms_merge_and_clear_ms(ms(), old_ms); } if (dir == GPRS_RLCMAC_UL_TBF) - ms()->set_tlli(tlli); + ms_set_tlli(ms(), tlli); else - ms()->confirm_tlli(tlli); + ms_confirm_tlli(ms(), tlli); } static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf) @@ -745,7 +740,7 @@ int gprs_rlcmac_tbf::setup(int8_t use_trx, bool single_slot) struct gprs_rlcmac_bts *bts_data = bts->bts_data(); int rc; - if (m_ms->mode() != GPRS) + if (ms_mode(m_ms) != GPRS) enable_egprs(); m_created_ts = time(NULL); @@ -775,7 +770,7 @@ int gprs_rlcmac_tbf::setup(int8_t use_trx, bool single_slot) return -1; } - m_ms->attach_tbf(this); + ms_attach_tbf(m_ms, this); return 0; } @@ -895,7 +890,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts) } if (ms()) - new_dl_tbf = ms()->dl_tbf(); + new_dl_tbf = ms_dl_tbf(ms()); if (!new_dl_tbf) { LOGPTBFDL(this, LOGL_ERROR, @@ -1012,7 +1007,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn, uint8_t ts) return NULL; if (ms()) - new_tbf = ms()->ul_tbf(); + new_tbf = ms_ul_tbf(ms()); if (!new_tbf) { LOGPTBFUL(this, LOGL_ERROR, "We have a schedule for uplink assignment, but there is no uplink TBF\n"); @@ -1170,3 +1165,58 @@ bool gprs_rlcmac_tbf::is_control_ts(uint8_t ts) const { return ts == control_ts; } + +/* C API */ +enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->state; +} + +enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->direction; +} + +void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, GprsMs *ms) +{ + tbf->set_ms(ms); +} + +struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf) +{ + return &tbf->m_ms_list.list; +} + +struct GprsMs *tbf_ms(struct gprs_rlcmac_tbf *tbf) +{ + return tbf->ms(); +} + +bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t) +{ + return tbf->timers_pending(t); +} + +struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf) +{ + return &tbf->m_llc; +} + +uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->first_common_ts; +} + +uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->dl_slots(); +} +uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->ul_slots(); +} + +bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->is_tfi_assigned(); +} @@ -25,11 +25,21 @@ #include "llc.h" #include "rlc.h" #include "cxx_linuxlist.h" +#include "pcu_utils.h" #include <gprs_debug.h> #include <gsm_timer.h> #include <stdint.h> +struct bssgp_bvc_ctx; +struct gprs_rlcmac_bts; + +#endif + +struct GprsMs; + +#ifdef __cplusplus extern "C" { +#endif #include <osmocom/core/utils.h> #include <osmocom/core/linuxlist.h> #include <osmocom/core/logging.h> @@ -37,12 +47,8 @@ extern "C" { #include <osmocom/gsm/gsm48.h> #include "coding_scheme.h" +#ifdef __cplusplus } - -struct bssgp_bvc_ctx; -class GprsMs; -struct gprs_rlcmac_bts; - #endif /* @@ -182,6 +188,28 @@ enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */ #define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0) #ifdef __cplusplus +extern "C" { +#endif +struct gprs_rlcmac_tbf; +const char *tbf_name(struct gprs_rlcmac_tbf *tbf); +enum gprs_rlcmac_tbf_state 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); +struct GprsMs *tbf_ms(struct gprs_rlcmac_tbf *tbf); +bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t); +void tbf_free(struct gprs_rlcmac_tbf *tbf); +struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf); +uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf); +uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf); +uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf); +bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf); +int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus struct gprs_rlcmac_tbf { gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir); @@ -255,7 +283,6 @@ struct gprs_rlcmac_tbf { void set_ta(uint8_t); uint8_t ms_class() const; enum CodingScheme current_cs() const; - size_t llc_queue_size() const; time_t created_ts() const; uint8_t dl_slots() const; @@ -269,9 +296,6 @@ struct gprs_rlcmac_tbf { /* attempt to make things a bit more fair */ void rotate_in_list(); - LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;} - const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;} - LListHead<gprs_rlcmac_tbf>& list(); const LListHead<gprs_rlcmac_tbf>& list() const; @@ -321,6 +345,8 @@ struct gprs_rlcmac_tbf { time_t m_created_ts; struct rate_ctr_group *m_ctrs; + enum gprs_rlcmac_tbf_state state; + struct llist_item m_ms_list; protected: gprs_rlcmac_bts *bts_data() const; @@ -331,26 +357,20 @@ protected: static const char *tbf_state_name[6]; - class GprsMs *m_ms; + struct GprsMs *m_ms; private: void enable_egprs(); - enum gprs_rlcmac_tbf_state state; enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state; enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state; enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state; enum gprs_rlcmac_tbf_poll_state poll_state; LListHead<gprs_rlcmac_tbf> m_list; - LListHead<gprs_rlcmac_tbf> m_ms_list; bool m_egprs_enabled; struct osmo_timer_list Tarr[T_MAX]; uint8_t Narr[N_MAX]; mutable char m_name_buf[60]; }; -void tbf_free(struct gprs_rlcmac_tbf *tbf); - -int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf); - inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const { return state == rhs; @@ -381,8 +401,6 @@ inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const return state != rhs; } -const char *tbf_name(gprs_rlcmac_tbf *tbf); - inline const char *gprs_rlcmac_tbf::state_name() const { return tbf_state_name[state]; diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index bb89e819..613f7b81 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -131,7 +131,7 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs LOGP(DTBF, LOGL_DEBUG, "********** DL-TBF starts here **********\n"); LOGP(DTBF, LOGL_INFO, "Allocating DL TBF: MS_CLASS=%d/%d\n", - ms->ms_class(), ms->egprs_ms_class()); + ms_ms_class(ms), ms_egprs_ms_class(ms)); tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); @@ -241,7 +241,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, GprsMs *ms, struct gprs_rlcmac_ul_tbf *ul_tbf = NULL, *old_ul_tbf; struct gprs_rlcmac_dl_tbf *dl_tbf = NULL; - ul_tbf = ms->ul_tbf(); + ul_tbf = ms_ul_tbf(ms); if (ul_tbf && ul_tbf->m_contention_resolution_done && !ul_tbf->m_final_ack_sent) { @@ -291,41 +291,43 @@ int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts, /* check for existing TBF */ ms = bts->bts->ms_store().get_ms(tlli, tlli_old, imsi); - if (ms && strlen(ms->imsi()) == 0) { + if (ms && strlen(ms_imsi(ms)) == 0) { ms_old = bts->bts->ms_store().get_ms(0, 0, imsi); if (ms_old && ms_old != ms) { /* The TLLI has changed (RAU), so there are two MS * objects for the same MS */ LOGP(DTBF, LOGL_NOTICE, "There is a new MS object for the same MS: (0x%08x, '%s') -> (0x%08x, '%s')\n", - ms_old->tlli(), ms_old->imsi(), ms->tlli(), ms->imsi()); + ms_tlli(ms_old), ms_imsi(ms_old), ms_tlli(ms), ms_imsi(ms)); - GprsMs::Guard guard_old(ms_old); + ms_ref(ms_old); - if (!ms->dl_tbf() && ms_old->dl_tbf()) { + if (!ms_dl_tbf(ms) && ms_dl_tbf(ms_old)) { LOGP(DTBF, LOGL_NOTICE, "IMSI %s, old TBF %s: moving DL TBF to new MS object\n", - imsi, ms_old->dl_tbf()->name()); - dl_tbf = ms_old->dl_tbf(); + imsi, ms_dl_tbf(ms_old)->name()); + dl_tbf = ms_dl_tbf(ms_old); /* Move the DL TBF to the new MS */ dl_tbf->set_ms(ms); } - ms->merge_and_clear_ms(ms_old); + ms_merge_and_clear_ms(ms, ms_old); + + ms_unref(ms_old); } } if (!ms) ms = bts->bts->ms_alloc(ms_class, egprs_ms_class); - ms->set_imsi(imsi); - ms->confirm_tlli(tlli); - if (!ms->ms_class() && ms_class) { - ms->set_ms_class(ms_class); + ms_set_imsi(ms, imsi); + ms_confirm_tlli(ms, tlli); + if (!ms_ms_class(ms) && ms_class) { + ms_set_ms_class(ms, ms_class); } - if (!ms->egprs_ms_class() && egprs_ms_class) { - ms->set_egprs_ms_class(egprs_ms_class); + if (!ms_egprs_ms_class(ms) && egprs_ms_class) { + ms_set_egprs_ms_class(ms, egprs_ms_class); } - dl_tbf = ms->dl_tbf(); + dl_tbf = ms_dl_tbf(ms); if (!dl_tbf) { rc = tbf_new_dl_assignment(bts, ms, &dl_tbf); if (rc < 0) @@ -344,7 +346,7 @@ struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx) uint32_t octets = 0, frames = 0; struct timespec hyst_delta = {0, 0}; const unsigned keep_small_thresh = 60; - const gprs_llc_queue::MetaInfo *info; + const MetaInfo *info; if (bts_data()->llc_discard_csec) csecs_to_timespec(bts_data()->llc_discard_csec, &hyst_delta); @@ -358,9 +360,9 @@ struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx) gprs_bssgp_update_queue_delay(tv_recv, &tv_now); - if (ms() && ms()->codel_state()) { - int bytes = llc_queue()->octets(); - if (gprs_codel_control(ms()->codel_state(), + if (ms() && ms_codel_state(ms())) { + int bytes = llc_queue_octets(llc_queue()); + if (gprs_codel_control(ms_codel_state(ms()), tv_recv, &tv_now, bytes)) goto drop_frame; } @@ -402,7 +404,7 @@ drop_frame: LOGPTBFDL(this, LOGL_NOTICE, "Discarding LLC PDU " "because lifetime limit reached, " "count=%u new_queue_size=%zu\n", - frames, llc_queue_size()); + frames, llc_queue_size(llc_queue())); if (frames > 0xff) frames = 0xff; if (octets > 0xffffff) @@ -459,7 +461,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, } else if (bsn < 0 && is_egprs_enabled() && req_mcs_kind == EGPRS_GMSK) { /* New data to be sent for EGPRS TBF but we are required to downgrade to * MCS1-4, because USF for GPRS-only MS will be sent */ - force_cs = m_ms->current_cs_dl(); + force_cs = ms_current_cs_dl(m_ms); if (force_cs > MCS4) { force_cs = bts->cs_dl_is_supported(MCS4) ? MCS4 : bts->cs_dl_is_supported(MCS3) ? MCS3 : @@ -467,7 +469,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, MCS1; LOGPTBFDL(this, LOGL_DEBUG, "Force downgrading DL %s -> %s due to USF for GPRS-only MS\n", - mcs_name(m_ms->current_cs_dl()), mcs_name(force_cs)); + mcs_name(ms_current_cs_dl(m_ms)), mcs_name(force_cs)); } } @@ -483,14 +485,14 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, if (is_egprs_enabled()) { /* Table 8.1.1.2 and Table 8.1.1.1 of 44.060 */ m_rlc.block(bsn)->cs_current_trans = get_retx_mcs(m_rlc.block(bsn)->cs_init, - ms()->current_cs_dl(), + ms_current_cs_dl(ms()), !bts->bts_data()->dl_arq_type); LOGPTBFDL(this, LOGL_DEBUG, "initial_cs_dl(%s) last_mcs(%s) demanded_mcs(%s) cs_trans(%s) arq_type(%d) bsn(%d)\n", mcs_name(m_rlc.block(bsn)->cs_init), mcs_name(m_rlc.block(bsn)->cs_last), - mcs_name(ms()->current_cs_dl()), + mcs_name(ms_current_cs_dl(ms())), mcs_name(m_rlc.block(bsn)->cs_current_trans), bts->bts_data()->dl_arq_type, bsn); @@ -635,7 +637,7 @@ void gprs_rlcmac_dl_tbf::schedule_next_frame() { struct msgb *msg; - if (m_llc.frame_length() != 0) + if (llc_frame_length(&m_llc) != 0) return; /* dequeue next LLC frame, if any */ @@ -661,7 +663,7 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) int write_offset = 0; Encoding::AppendResult ar; - if (m_llc.frame_length() == 0) + if (llc_frame_length(&m_llc) == 0) schedule_next_frame(); OSMO_ASSERT(mcs_is_valid(cs)); @@ -693,7 +695,7 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) bool is_final; int payload_written = 0; - if (m_llc.frame_length() == 0) { + if (llc_frame_length(&m_llc) == 0) { /* It is not clear, when the next real data will * arrive, so request a DL ack/nack now */ request_dl_ack(); @@ -731,10 +733,10 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) LOGPTBFDL(this, LOGL_DEBUG, "Empty chunk, added LLC dummy command of size %d, drained_since=%d\n", - m_llc.frame_length(), frames_since_last_drain(fn)); + llc_frame_length(&m_llc), frames_since_last_drain(fn)); } - is_final = llc_queue_size() == 0 && !keep_open(fn); + is_final = llc_queue_size(llc_queue()) == 0 && !keep_open(fn); ar = Encoding::rlc_data_to_dl_append(rdbi, cs, &m_llc, &write_offset, &num_chunks, data, is_final, &payload_written); @@ -745,9 +747,9 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, enum CodingScheme cs) if (ar == Encoding::AR_NEED_MORE_BLOCKS) break; - LOGPTBFDL(this, LOGL_DEBUG, "Complete DL frame, len=%d\n", m_llc.frame_length()); - gprs_rlcmac_dl_bw(this, m_llc.frame_length()); - bts->do_rate_ctr_add(CTR_LLC_DL_BYTES, m_llc.frame_length()); + LOGPTBFDL(this, LOGL_DEBUG, "Complete DL frame, len=%d\n", llc_frame_length(&m_llc)); + gprs_rlcmac_dl_bw(this, llc_frame_length(&m_llc)); + bts->do_rate_ctr_add(CTR_LLC_DL_BYTES, llc_frame_length(&m_llc)); m_llc.reset(); if (is_final) { @@ -1131,7 +1133,7 @@ int gprs_rlcmac_dl_tbf::update_window(unsigned first_bsn, error_rate = analyse_errors(show_rbb, behind_last_bsn, &ana_res); if (bts_data()->cs_adj_enabled && ms()) - ms()->update_error_rate(this, error_rate); + ms_update_error_rate(ms(), this, error_rate); m_window.update(bts, rbb, first_bsn, &lost, &received); rate_ctr_add(&m_ctrs->ctr[TBF_CTR_RLC_NACKED], lost); @@ -1186,7 +1188,7 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) error_rate = analyse_errors(show_rbb, ssn, &ana_res); if (bts_data()->cs_adj_enabled && ms()) - ms()->update_error_rate(this, error_rate); + ms_update_error_rate(ms(), this, error_rate); m_window.update(bts, show_rbb, ssn, &lost, &received); @@ -1221,7 +1223,7 @@ int gprs_rlcmac_dl_tbf::maybe_start_new_window() release(); /* check for LLC PDU in the LLC Queue */ - if (llc_queue_size() > 0) + if (llc_queue_size(llc_queue()) > 0) /* we have more data so we will re-use this tbf */ establish_dl_tbf_on_pacch(); @@ -1331,8 +1333,8 @@ bool gprs_rlcmac_dl_tbf::need_control_ts() const bool gprs_rlcmac_dl_tbf::have_data() const { - return m_llc.chunk_size() > 0 || - (llc_queue_size() > 0); + return llc_chunk_size(&m_llc) > 0 || + (llc_queue_size(llc_queue()) > 0); } static inline int frames_since_last(int32_t last, unsigned fn) @@ -1556,3 +1558,11 @@ void gprs_rlcmac_dl_tbf::update_coding_scheme_counter_dl(enum CodingScheme cs) mcs_name(cs)); } } + +struct gprs_rlcmac_dl_tbf *as_dl_tbf(struct gprs_rlcmac_tbf *tbf) +{ + if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF) + return static_cast<gprs_rlcmac_dl_tbf *>(tbf); + else + return NULL; +} diff --git a/src/tbf_dl.h b/src/tbf_dl.h index ffb370c3..3cd88c9e 100644 --- a/src/tbf_dl.h +++ b/src/tbf_dl.h @@ -141,15 +141,17 @@ inline uint16_t gprs_rlcmac_dl_tbf::window_size() const return m_window.ws(); } -inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf) -{ - if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF) - return static_cast<gprs_rlcmac_dl_tbf *>(tbf); - else - return NULL; -} - struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot); +#else /* ifdef __cplusplus */ +struct gprs_rlcmac_dl_tbf; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +struct gprs_rlcmac_dl_tbf *as_dl_tbf(struct gprs_rlcmac_tbf *tbf); +#ifdef __cplusplus +} #endif diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 80a8eaa4..f8c860c9 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -105,7 +105,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs LOGP(DTBF, LOGL_DEBUG, "********** UL-TBF starts here **********\n"); LOGP(DTBF, LOGL_INFO, "Allocating UL TBF: MS_CLASS=%d/%d\n", - ms->ms_class(), ms->egprs_ms_class()); + ms_ms_class(ms), ms_egprs_ms_class(ms)); tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); if (!tbf) @@ -172,7 +172,7 @@ struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts, if (!ms) ms = bts->bts->ms_alloc(0, 0); - ms->set_tlli(tlli); + ms_set_tlli(ms, tlli); ul_tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); if (!ul_tbf) @@ -185,7 +185,7 @@ struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts, ul_tbf->bts->do_rate_ctr_inc(CTR_TBF_UL_ALLOCATED); TBF_SET_ASS_ON(ul_tbf, GPRS_RLCMAC_FLAG_PACCH, false); - ms->attach_tbf(ul_tbf); + ms_attach_tbf(ms, ul_tbf); ul_tbf->update_ms(tlli, GPRS_RLCMAC_UL_TBF); TBF_SET_ASS_STATE_UL(ul_tbf, GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ); ul_tbf->control_ts = ts; @@ -252,14 +252,14 @@ int gprs_rlcmac_ul_tbf::assemble_forward_llc(const gprs_rlc_data *_data) frame->is_complete); m_llc.append_frame(data + frame->offset, frame->length); - m_llc.consume(frame->length); + llc_consume(&m_llc, frame->length); } if (frame->is_complete) { /* send frame to SGSN */ - LOGPTBFUL(this, LOGL_DEBUG, "complete UL frame len=%d\n", m_llc.frame_length()); + LOGPTBFUL(this, LOGL_DEBUG, "complete UL frame len=%d\n", llc_frame_length(&m_llc)); snd_ul_ud(); - bts->do_rate_ctr_add(CTR_LLC_UL_BYTES, m_llc.frame_length()); + bts->do_rate_ctr_add(CTR_LLC_UL_BYTES, llc_frame_length(&m_llc)); m_llc.reset(); } } @@ -357,7 +357,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged( /* store measurement values */ if (ms()) - ms()->update_l1_meas(meas); + ms_update_l1_meas(ms(), meas); uint32_t new_tlli = GSM_RESERVED_TMSI; unsigned int block_idx; @@ -559,10 +559,10 @@ int gprs_rlcmac_ul_tbf::snd_ul_ud() { uint8_t qos_profile[3]; struct msgb *llc_pdu; - unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + m_llc.frame_length(); + unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + llc_frame_length(&m_llc); struct bssgp_bvc_ctx *bctx = gprs_bssgp_pcu_current_bctx(); - LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), m_llc.frame_length()); + LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), llc_frame_length(&m_llc)); if (!bctx) { LOGP(DBSSGP, LOGL_ERROR, "No bctx\n"); m_llc.reset_frame_space(); @@ -570,8 +570,8 @@ int gprs_rlcmac_ul_tbf::snd_ul_ud() } llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu"); - uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*m_llc.frame_length())); - tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*m_llc.frame_length(), m_llc.frame); + uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*llc_frame_length(&m_llc))); + tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*llc_frame_length(&m_llc), m_llc.frame); qos_profile[0] = QOS_PROFILE >> 16; qos_profile[1] = QOS_PROFILE >> 8; qos_profile[2] = QOS_PROFILE; @@ -772,3 +772,11 @@ gprs_rlc_window *gprs_rlcmac_ul_tbf::window() { return &m_window; } + +struct gprs_rlcmac_ul_tbf *as_ul_tbf(struct gprs_rlcmac_tbf *tbf) +{ + if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) + return static_cast<gprs_rlcmac_ul_tbf *>(tbf); + else + return NULL; +} diff --git a/src/tbf_ul.h b/src/tbf_ul.h index 9ccdf620..1d9cf50c 100644 --- a/src/tbf_ul.h +++ b/src/tbf_ul.h @@ -108,32 +108,28 @@ protected: gprs_rlc_ul_window m_window; }; -#ifdef __cplusplus -extern "C" { -#endif -void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta); -void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta); -#ifdef __cplusplus -} -#endif - inline uint16_t gprs_rlcmac_ul_tbf::window_size() const { return m_window.ws(); } -inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf) -{ - if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) - return static_cast<gprs_rlcmac_ul_tbf *>(tbf); - else - return NULL; -} - struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot); struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint32_t tlli); struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts, GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no); +#else /* ifdef __cplusplus */ +struct gprs_rlcmac_ul_tbf; +#endif + + +#ifdef __cplusplus +extern "C" { +#endif +void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta); +void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta); +struct gprs_rlcmac_ul_tbf *as_ul_tbf(struct gprs_rlcmac_tbf *tbf); +#ifdef __cplusplus +} #endif diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp index 8ebf1594..17cee462 100644 --- a/tests/alloc/AllocTest.cpp +++ b/tests/alloc/AllocTest.cpp @@ -224,12 +224,12 @@ static inline bool test_alloc_b_ul_dl(bool ts0, bool ts1, bool ts2, bool ts3, bo return false; OSMO_ASSERT(ul_tbf->ms()); - OSMO_ASSERT(ul_tbf->ms()->current_trx()); + OSMO_ASSERT(ms_current_trx(ul_tbf->ms())); dump_assignment(ul_tbf, "UL", verbose); /* assume final ack has not been sent */ - dl_tbf = tbf_alloc_dl_tbf(bts, ms, ms->current_trx()->trx_no, false); + dl_tbf = tbf_alloc_dl_tbf(bts, ms, ms_current_trx(ms)->trx_no, false); if (!dl_tbf) return false; @@ -268,11 +268,11 @@ static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bo dl_tbf->update_ms(0x23, GPRS_RLCMAC_DL_TBF); OSMO_ASSERT(dl_tbf->ms() == ms); - OSMO_ASSERT(dl_tbf->ms()->current_trx()); + OSMO_ASSERT(ms_current_trx(dl_tbf->ms())); dump_assignment(dl_tbf, "DL", verbose); - ul_tbf = tbf_alloc_ul_tbf(bts, ms, ms->current_trx()->trx_no, false); + ul_tbf = tbf_alloc_ul_tbf(bts, ms, ms_current_trx(ms)->trx_no, false); if (!ul_tbf) return false; @@ -319,8 +319,8 @@ static inline bool test_alloc_b_jolly(uint8_t ms_class) return false; OSMO_ASSERT(ul_tbf->ms() == ms); - OSMO_ASSERT(ul_tbf->ms()->current_trx()); - trx_no = ms->current_trx()->trx_no; + OSMO_ASSERT(ms_current_trx(ul_tbf->ms())); + trx_no = ms_current_trx(ms)->trx_no; dump_assignment(ul_tbf, "UL", true); /* assume final ack has not been sent */ @@ -453,50 +453,55 @@ static inline char *test_mode_descr(enum test_mode t) } } -static GprsMs *alloc_tbfs(BTS *the_bts, GprsMs *ms, enum test_mode mode) +static GprsMs *alloc_tbfs(BTS *the_bts, struct GprsMs *old_ms, enum test_mode mode) { struct gprs_rlcmac_bts *bts; + struct GprsMs *ms, *new_ms; uint8_t trx_no = -1; - OSMO_ASSERT(ms != NULL); + OSMO_ASSERT(old_ms != NULL); bts = the_bts->bts_data(); gprs_rlcmac_tbf *tbf = NULL; - if (ms && ms->current_trx()) - trx_no = ms->current_trx()->trx_no; + if (ms_current_trx(old_ms)) + trx_no = ms_current_trx(old_ms)->trx_no; - GprsMs::Guard guard1(ms); + ms_ref(old_ms); /* Allocate what is needed first */ switch (mode) { case TEST_MODE_UL_ONLY: case TEST_MODE_DL_AFTER_UL: case TEST_MODE_UL_AND_DL: - if (ms->ul_tbf()) - tbf_free(ms->ul_tbf()); - tbf = tbf_alloc_ul_tbf(bts, ms, trx_no, false); - if (tbf == NULL) + if (ms_ul_tbf(old_ms)) + tbf_free(ms_ul_tbf(old_ms)); + tbf = tbf_alloc_ul_tbf(bts, old_ms, trx_no, false); + if (tbf == NULL) { + ms_unref(old_ms); return NULL; + } break; case TEST_MODE_DL_ONLY: case TEST_MODE_UL_AFTER_DL: case TEST_MODE_DL_AND_UL: - if (ms->dl_tbf()) - tbf_free(ms->dl_tbf()); - tbf = tbf_alloc_dl_tbf(bts, ms, trx_no, false); - if (tbf == NULL) + if (ms_dl_tbf(old_ms)) + tbf_free(ms_dl_tbf(old_ms)); + tbf = tbf_alloc_dl_tbf(bts, old_ms, trx_no, false); + if (tbf == NULL) { + ms_unref(old_ms); return NULL; + } } OSMO_ASSERT(tbf); OSMO_ASSERT(tbf->ms()); - OSMO_ASSERT(ms == NULL || ms == tbf->ms()); + OSMO_ASSERT(old_ms == tbf->ms()); ms = tbf->ms(); - GprsMs::Guard guard2(ms); - + ms_ref(ms); + new_ms = ms; /* Continue with what is needed next */ switch (mode) { case TEST_MODE_UL_ONLY: @@ -506,12 +511,12 @@ static GprsMs *alloc_tbfs(BTS *the_bts, GprsMs *ms, enum test_mode mode) case TEST_MODE_DL_AFTER_UL: case TEST_MODE_UL_AND_DL: - ms = alloc_tbfs(the_bts, ms, TEST_MODE_DL_ONLY); + new_ms = alloc_tbfs(the_bts, ms, TEST_MODE_DL_ONLY); break; case TEST_MODE_UL_AFTER_DL: case TEST_MODE_DL_AND_UL: - ms = alloc_tbfs(the_bts, ms, TEST_MODE_UL_ONLY); + new_ms = alloc_tbfs(the_bts, ms, TEST_MODE_UL_ONLY); break; } @@ -527,10 +532,12 @@ static GprsMs *alloc_tbfs(BTS *the_bts, GprsMs *ms, enum test_mode mode) break; } - if (!ms && tbf) + if (!new_ms && tbf) tbf_free(tbf); - return guard2.is_idle() ? NULL : ms; + ms_unref(old_ms); + ms_unref(ms); + return new_ms; } static unsigned alloc_many_tbfs(BTS *the_bts, unsigned min_class, @@ -556,16 +563,16 @@ static unsigned alloc_many_tbfs(BTS *the_bts, unsigned min_class, ms = the_bts->ms_by_tlli(tlli); if (!ms) ms = the_bts->ms_alloc(0, 0); - ms->set_ms_class(ms_class); + ms_set_ms_class(ms, ms_class); ms = alloc_tbfs(the_bts, ms, mode); if (!ms) break; - ms->set_tlli(tlli); + ms_set_tlli(ms, tlli); - ul_tbf = ms->ul_tbf(); - dl_tbf = ms->dl_tbf(); - trx = ms->current_trx(); + ul_tbf = ms_ul_tbf(ms); + dl_tbf = ms_dl_tbf(ms); + trx = ms_current_trx(ms); OSMO_ASSERT(ul_tbf || dl_tbf); @@ -616,12 +623,12 @@ static unsigned alloc_many_tbfs(BTS *the_bts, unsigned min_class, get_dir_char(0x80, ul_slots, dl_slots, busy_slots)); if (tfi >= 0) { - OSMO_ASSERT(ms->current_trx()); + OSMO_ASSERT(ms_current_trx(ms)); tfi2 = the_bts->tfi_find_free(dir, &trx_no2, - ms->current_trx()->trx_no); + ms_current_trx(ms)->trx_no); OSMO_ASSERT(tfi != tfi2); OSMO_ASSERT(tfi2 < 0 || - trx_no2 == ms->current_trx()->trx_no); + trx_no2 == ms_current_trx(ms)->trx_no); } ms_class += 1; diff --git a/tests/app_info/AppInfoTest.cpp b/tests/app_info/AppInfoTest.cpp index cd4454d1..6e335389 100644 --- a/tests/app_info/AppInfoTest.cpp +++ b/tests/app_info/AppInfoTest.cpp @@ -152,9 +152,9 @@ void cleanup() { fprintf(stderr, "--- %s ---\n", __func__); + tbf_free(tbf1); + tbf_free(tbf2); BTS::main_bts()->cleanup(); - talloc_free(tbf1); - talloc_free(tbf2); /* FIXME: talloc report disabled, because bts->ms_alloc() in prepare_bts_with_two_dl_tbf_subscr() causes leak */ /* talloc_report_full(tall_pcu_ctx, stderr); */ talloc_free(tall_pcu_ctx); diff --git a/tests/app_info/AppInfoTest.err b/tests/app_info/AppInfoTest.err index ae20ea38..9b0910f2 100644 --- a/tests/app_info/AppInfoTest.err +++ b/tests/app_info/AppInfoTest.err @@ -52,3 +52,14 @@ Previous Packet Application Information was not sent to all subscribers, overwri Sending Packet Application Information to 2 subscribers with active TBF --- cleanup --- +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002. +PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002. +PDCH(TS 6, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002. +PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffffffff, TBF = TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS) +PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 5, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +PDCH(TS 6, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffffffff, TBF = TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffffffff +Destroying MS object, TLLI = 0xffffffff diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp index 67ed2a73..8fa76dd5 100644 --- a/tests/edge/EdgeTest.cpp +++ b/tests/edge/EdgeTest.cpp @@ -619,7 +619,7 @@ static void test_rlc_unit_encoder() write_offset = 0; memset(data, 0, sizeof(data)); - OSMO_ASSERT(llc.chunk_size() == 1); + OSMO_ASSERT(llc_chunk_size(&llc) == 1); count_payload = -1; @@ -767,7 +767,7 @@ static void test_rlc_unit_encoder() write_offset = 0; memset(data, 0, sizeof(data)); - OSMO_ASSERT(llc.chunk_size() == 10); + OSMO_ASSERT(llc_chunk_size(&llc) == 10); count_payload = -1; ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, @@ -899,7 +899,7 @@ static void test_rlc_unit_encoder() write_offset = 0; memset(data, 0, sizeof(data)); - OSMO_ASSERT(llc.chunk_size() == 0); + OSMO_ASSERT(llc_chunk_size(&llc) == 0); count_payload = -1; ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, @@ -1167,7 +1167,6 @@ static void uplink_header_type_2_parsing_test(BTS *the_bts, uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, uint8_t ms_class) { - struct pcu_l1_meas meas; int tfi = 0; uint8_t data[79] = {0}; struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL; diff --git a/tests/llc/LlcTest.cpp b/tests/llc/LlcTest.cpp index 10cd96bd..bfcac778 100644 --- a/tests/llc/LlcTest.cpp +++ b/tests/llc/LlcTest.cpp @@ -60,10 +60,10 @@ static void enqueue_data(gprs_llc_queue *queue, const uint8_t *data, size_t len, } static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data, - size_t len, const gprs_llc_queue::MetaInfo *exp_info) + size_t len, const MetaInfo *exp_info) { struct msgb *llc_msg; - const gprs_llc_queue::MetaInfo *info_res; + const MetaInfo *info_res; llc_msg = queue->dequeue(&info_res); OSMO_ASSERT(llc_msg != NULL); @@ -88,7 +88,7 @@ static void enqueue_data(gprs_llc_queue *queue, const char *message, } static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message, - const gprs_llc_queue::MetaInfo *exp_info = 0) + const MetaInfo *exp_info = 0) { dequeue_and_check(queue, (uint8_t *)(exp_message), strlen(exp_message), exp_info); @@ -101,33 +101,33 @@ static void test_llc_queue() printf("=== start %s ===\n", __func__); - queue.init(); - OSMO_ASSERT(queue.size() == 0); - OSMO_ASSERT(queue.octets() == 0); + llc_queue_init(&queue); + OSMO_ASSERT(llc_queue_size(&queue) == 0); + OSMO_ASSERT(llc_queue_octets(&queue) == 0); enqueue_data(&queue, "LLC message", &expire_time); - OSMO_ASSERT(queue.size() == 1); - OSMO_ASSERT(queue.octets() == 11); + OSMO_ASSERT(llc_queue_size(&queue) == 1); + OSMO_ASSERT(llc_queue_octets(&queue) == 11); enqueue_data(&queue, "other LLC message", &expire_time); - OSMO_ASSERT(queue.size() == 2); - OSMO_ASSERT(queue.octets() == 28); + OSMO_ASSERT(llc_queue_size(&queue) == 2); + OSMO_ASSERT(llc_queue_octets(&queue) == 28); dequeue_and_check(&queue, "LLC message"); - OSMO_ASSERT(queue.size() == 1); - OSMO_ASSERT(queue.octets() == 17); + OSMO_ASSERT(llc_queue_size(&queue) == 1); + OSMO_ASSERT(llc_queue_octets(&queue) == 17); dequeue_and_check(&queue, "other LLC message"); - OSMO_ASSERT(queue.size() == 0); - OSMO_ASSERT(queue.octets() == 0); + OSMO_ASSERT(llc_queue_size(&queue) == 0); + OSMO_ASSERT(llc_queue_octets(&queue) == 0); enqueue_data(&queue, "LLC", &expire_time); - OSMO_ASSERT(queue.size() == 1); - OSMO_ASSERT(queue.octets() == 3); + OSMO_ASSERT(llc_queue_size(&queue) == 1); + OSMO_ASSERT(llc_queue_octets(&queue) == 3); - queue.clear(NULL); - OSMO_ASSERT(queue.size() == 0); - OSMO_ASSERT(queue.octets() == 0); + llc_queue_clear(&queue, NULL); + OSMO_ASSERT(llc_queue_size(&queue) == 0); + OSMO_ASSERT(llc_queue_octets(&queue) == 0); printf("=== end %s ===\n", __func__); } @@ -135,14 +135,14 @@ static void test_llc_queue() static void test_llc_meta() { gprs_llc_queue queue; - gprs_llc_queue::MetaInfo info1 = {0}; - gprs_llc_queue::MetaInfo info2 = {0}; + MetaInfo info1 = {0}; + MetaInfo info2 = {0}; printf("=== start %s ===\n", __func__); - queue.init(); - OSMO_ASSERT(queue.size() == 0); - OSMO_ASSERT(queue.octets() == 0); + llc_queue_init(&queue); + OSMO_ASSERT(llc_queue_size(&queue) == 0); + OSMO_ASSERT(llc_queue_octets(&queue) == 0); info1.recv_time.tv_sec = 123456777; info1.recv_time.tv_nsec = 123456000; @@ -161,9 +161,9 @@ static void test_llc_meta() dequeue_and_check(&queue, "LLC message 1", &info1); dequeue_and_check(&queue, "LLC message 2", &info2); - queue.clear(NULL); - OSMO_ASSERT(queue.size() == 0); - OSMO_ASSERT(queue.octets() == 0); + llc_queue_clear(&queue, NULL); + OSMO_ASSERT(llc_queue_size(&queue) == 0); + OSMO_ASSERT(llc_queue_octets(&queue) == 0); printf("=== end %s ===\n", __func__); } @@ -176,8 +176,8 @@ static void test_llc_merge() printf("=== start %s ===\n", __func__); - queue1.init(); - queue2.init(); + llc_queue_init(&queue1); + llc_queue_init(&queue2); clk_mono_override_time->tv_sec += 1; enqueue_data(&queue1, "*A*", &expire_time); @@ -194,17 +194,17 @@ static void test_llc_merge() clk_mono_override_time->tv_sec += 1; enqueue_data(&queue2, "*E*", &expire_time); - OSMO_ASSERT(queue1.size() == 3); - OSMO_ASSERT(queue1.octets() == 9); - OSMO_ASSERT(queue2.size() == 2); - OSMO_ASSERT(queue2.octets() == 6); + OSMO_ASSERT(llc_queue_size(&queue1) == 3); + OSMO_ASSERT(llc_queue_octets(&queue1) == 9); + OSMO_ASSERT(llc_queue_size(&queue2) == 2); + OSMO_ASSERT(llc_queue_octets(&queue2) == 6); - queue2.move_and_merge(&queue1); + llc_queue_move_and_merge(&queue2, &queue1); - OSMO_ASSERT(queue1.size() == 0); - OSMO_ASSERT(queue1.octets() == 0); - OSMO_ASSERT(queue2.size() == 5); - OSMO_ASSERT(queue2.octets() == 15); + OSMO_ASSERT(llc_queue_size(&queue1) == 0); + OSMO_ASSERT(llc_queue_octets(&queue1) == 0); + OSMO_ASSERT(llc_queue_size(&queue2) == 5); + OSMO_ASSERT(llc_queue_octets(&queue2) == 15); dequeue_and_check(&queue2, "*A*"); dequeue_and_check(&queue2, "*B*"); @@ -212,8 +212,8 @@ static void test_llc_merge() dequeue_and_check(&queue2, "*D*"); dequeue_and_check(&queue2, "*E*"); - OSMO_ASSERT(queue2.size() == 0); - OSMO_ASSERT(queue2.octets() == 0); + OSMO_ASSERT(llc_queue_size(&queue2) == 0); + OSMO_ASSERT(llc_queue_octets(&queue2) == 0); printf("=== end %s ===\n", __func__); } diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp index 4f47bc97..c164409a 100644 --- a/tests/ms/MsTest.cpp +++ b/tests/ms/MsTest.cpp @@ -56,33 +56,33 @@ static void test_ms_state() printf("=== start %s ===\n", __func__); - ms = new GprsMs(&the_bts, tlli); - OSMO_ASSERT(ms->is_idle()); + ms = ms_alloc(&the_bts, tlli); + OSMO_ASSERT(ms_is_idle(ms)); dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms); ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms); - ms->attach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - OSMO_ASSERT(ms->dl_tbf() == NULL); + ms_attach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); - ms->attach_tbf(dl_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); + ms_attach_tbf(ms, dl_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); - OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_UL_TBF) == ul_tbf); - OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_DL_TBF) == dl_tbf); + OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_UL_TBF) == ul_tbf); + OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_DL_TBF) == dl_tbf); - ms->detach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); + ms_detach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); - ms->detach_tbf(dl_tbf); + ms_detach_tbf(ms, dl_tbf); /* The ms object is freed now */ ms = NULL; @@ -92,6 +92,23 @@ static void test_ms_state() printf("=== end %s ===\n", __func__); } +static enum {CB_UNKNOWN, CB_IS_IDLE, CB_IS_ACTIVE} last_cb = CB_UNKNOWN; +static void ms_idle_cb(struct GprsMs *ms) +{ + OSMO_ASSERT(ms_is_idle(ms)); + printf(" ms_idle() was called\n"); + last_cb = CB_IS_IDLE; +} +static void ms_active_cb(struct GprsMs *ms) +{ + OSMO_ASSERT(!ms_is_idle(ms)); + printf(" ms_active() was called\n"); + last_cb = CB_IS_ACTIVE; +} +static struct gpr_ms_callback ms_cb = { + .ms_idle = ms_idle_cb, + .ms_active = ms_active_cb +}; static void test_ms_callback() { uint32_t tlli = 0xffeeddbb; @@ -99,63 +116,50 @@ static void test_ms_callback() gprs_rlcmac_ul_tbf *ul_tbf; BTS the_bts; GprsMs *ms; - static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN; - - struct MyCallback: public GprsMs::Callback { - virtual void ms_idle(class GprsMs *ms) { - OSMO_ASSERT(ms->is_idle()); - printf(" ms_idle() was called\n"); - last_cb = IS_IDLE; - } - virtual void ms_active(class GprsMs *ms) { - OSMO_ASSERT(!ms->is_idle()); - printf(" ms_active() was called\n"); - last_cb = IS_ACTIVE; - } - } cb; + last_cb = CB_UNKNOWN; printf("=== start %s ===\n", __func__); - ms = new GprsMs(&the_bts, tlli); - ms->set_callback(&cb); + ms = ms_alloc(&the_bts, tlli); + ms_set_callback(ms, &ms_cb); - OSMO_ASSERT(ms->is_idle()); + OSMO_ASSERT(ms_is_idle(ms)); dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms); ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms); - OSMO_ASSERT(last_cb == UNKNOWN); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->attach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - OSMO_ASSERT(ms->dl_tbf() == NULL); - OSMO_ASSERT(last_cb == IS_ACTIVE); + ms_attach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); + OSMO_ASSERT(last_cb == CB_IS_ACTIVE); - last_cb = UNKNOWN; + last_cb = CB_UNKNOWN; - ms->attach_tbf(dl_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); - OSMO_ASSERT(last_cb == UNKNOWN); + ms_attach_tbf(ms, dl_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->detach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); - OSMO_ASSERT(last_cb == UNKNOWN); + ms_detach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->detach_tbf(dl_tbf); - OSMO_ASSERT(ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == NULL); - OSMO_ASSERT(last_cb == IS_IDLE); + ms_detach_tbf(ms, dl_tbf); + OSMO_ASSERT(ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); + OSMO_ASSERT(last_cb == CB_IS_IDLE); - last_cb = UNKNOWN; - delete ms; + last_cb = CB_UNKNOWN; + talloc_free(ms); talloc_free(dl_tbf); talloc_free(ul_tbf); @@ -163,6 +167,22 @@ static void test_ms_callback() printf("=== end %s ===\n", __func__); } +static bool was_idle; +static void ms_replace_tbf_idle_cb(struct GprsMs *ms) +{ + OSMO_ASSERT(ms_is_idle(ms)); + printf(" ms_idle() was called\n"); + was_idle = true; +} +static void ms_replace_tbf_active_cb(struct GprsMs *ms) +{ + OSMO_ASSERT(!ms_is_idle(ms)); + printf(" ms_active() was called\n"); +} +static struct gpr_ms_callback ms_replace_tbf_cb = { + .ms_idle = ms_replace_tbf_idle_cb, + .ms_active = ms_replace_tbf_active_cb +}; static void test_ms_replace_tbf() { uint32_t tlli = 0xffeeddbb; @@ -170,26 +190,13 @@ static void test_ms_replace_tbf() gprs_rlcmac_ul_tbf *ul_tbf; BTS the_bts; GprsMs *ms; - static bool was_idle; - - struct MyCallback: public GprsMs::Callback { - virtual void ms_idle(class GprsMs *ms) { - OSMO_ASSERT(ms->is_idle()); - printf(" ms_idle() was called\n"); - was_idle = true; - } - virtual void ms_active(class GprsMs *ms) { - OSMO_ASSERT(!ms->is_idle()); - printf(" ms_active() was called\n"); - } - } cb; printf("=== start %s ===\n", __func__); - ms = new GprsMs(&the_bts, tlli); - ms->set_callback(&cb); + ms = ms_alloc(&the_bts, tlli); + ms_set_callback(ms, &ms_replace_tbf_cb); - OSMO_ASSERT(ms->is_idle()); + OSMO_ASSERT(ms_is_idle(ms)); was_idle = false; dl_tbf[0] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); @@ -199,49 +206,49 @@ static void test_ms_replace_tbf() ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms); - ms->attach_tbf(dl_tbf[0]); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf[0]); - OSMO_ASSERT(llist_empty(&ms->old_tbfs())); + ms_attach_tbf(ms, dl_tbf[0]); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[0]); + OSMO_ASSERT(llist_empty(&ms->old_tbfs)); OSMO_ASSERT(!was_idle); - ms->attach_tbf(dl_tbf[1]); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]); - OSMO_ASSERT(!llist_empty(&ms->old_tbfs())); + ms_attach_tbf(ms, dl_tbf[1]); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]); + OSMO_ASSERT(!llist_empty(&ms->old_tbfs)); OSMO_ASSERT(!was_idle); - ms->attach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]); - OSMO_ASSERT(!llist_empty(&ms->old_tbfs())); + ms_attach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]); + OSMO_ASSERT(!llist_empty(&ms->old_tbfs)); OSMO_ASSERT(!was_idle); - ms->detach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]); - OSMO_ASSERT(!llist_empty(&ms->old_tbfs())); + ms_detach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]); + OSMO_ASSERT(!llist_empty(&ms->old_tbfs)); OSMO_ASSERT(!was_idle); - ms->detach_tbf(dl_tbf[0]); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]); - OSMO_ASSERT(llist_empty(&ms->old_tbfs())); + ms_detach_tbf(ms, dl_tbf[0]); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]); + OSMO_ASSERT(llist_empty(&ms->old_tbfs)); OSMO_ASSERT(!was_idle); - ms->detach_tbf(dl_tbf[1]); - OSMO_ASSERT(ms->is_idle()); - OSMO_ASSERT(ms->ul_tbf() == NULL); - OSMO_ASSERT(ms->dl_tbf() == NULL); - OSMO_ASSERT(llist_empty(&ms->old_tbfs())); + ms_detach_tbf(ms, dl_tbf[1]); + OSMO_ASSERT(ms_is_idle(ms)); + OSMO_ASSERT(ms_ul_tbf(ms) == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); + OSMO_ASSERT(llist_empty(&ms->old_tbfs)); OSMO_ASSERT(was_idle); - delete ms; + talloc_free(ms); talloc_free(dl_tbf[0]); talloc_free(dl_tbf[1]); @@ -260,86 +267,86 @@ static void test_ms_change_tlli() printf("=== start %s ===\n", __func__); - ms = new GprsMs(&the_bts, start_tlli); + ms = ms_alloc(&the_bts, start_tlli); - OSMO_ASSERT(ms->is_idle()); + OSMO_ASSERT(ms_is_idle(ms)); /* MS announces TLLI, SGSN uses it immediately */ - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); - ms->confirm_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(!ms->check_tlli(start_tlli)); + ms_confirm_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(!ms_check_tlli(ms, start_tlli)); /* MS announces TLLI, SGSN uses it later */ - ms->set_tlli(start_tlli); - ms->confirm_tlli(start_tlli); + ms_set_tlli(ms, start_tlli); + ms_confirm_tlli(ms, start_tlli); - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); - ms->confirm_tlli(start_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); + ms_confirm_tlli(ms, start_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); - ms->confirm_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(!ms->check_tlli(start_tlli)); + ms_confirm_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(!ms_check_tlli(ms, start_tlli)); /* MS announces TLLI, SGSN uses it later after another new TLLI */ - ms->set_tlli(start_tlli); - ms->confirm_tlli(start_tlli); - - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); - - ms->confirm_tlli(other_sgsn_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli)); - - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli)); - - ms->confirm_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(!ms->check_tlli(start_tlli)); - OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli)); + ms_set_tlli(ms, start_tlli); + ms_confirm_tlli(ms, start_tlli); + + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); + + ms_confirm_tlli(ms, other_sgsn_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, other_sgsn_tlli)); + + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, other_sgsn_tlli)); + + ms_confirm_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(!ms_check_tlli(ms, start_tlli)); + OSMO_ASSERT(!ms_check_tlli(ms, other_sgsn_tlli)); /* SGSN uses the new TLLI before it is announced by the MS (shouldn't * happen in normal use) */ - ms->set_tlli(start_tlli); - ms->confirm_tlli(start_tlli); + ms_set_tlli(ms, start_tlli); + ms_confirm_tlli(ms, start_tlli); - ms->confirm_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == start_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(ms->check_tlli(start_tlli)); + ms_confirm_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == start_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(ms_check_tlli(ms, start_tlli)); - ms->set_tlli(new_ms_tlli); - OSMO_ASSERT(ms->tlli() == new_ms_tlli); - OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); - OSMO_ASSERT(!ms->check_tlli(start_tlli)); + ms_set_tlli(ms, new_ms_tlli); + OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli); + OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli)); + OSMO_ASSERT(!ms_check_tlli(ms, start_tlli)); - delete ms; + talloc_free(ms); printf("=== end %s ===\n", __func__); } @@ -353,9 +360,9 @@ static GprsMs *prepare_ms(GprsMsStorage *st, uint32_t tlli, enum gprs_rlcmac_tbf ms = st->create_ms(); if (dir == GPRS_RLCMAC_UL_TBF) - ms->set_tlli(tlli); + ms_set_tlli(ms, tlli); else - ms->confirm_tlli(tlli); + ms_confirm_tlli(ms, tlli); return ms; } @@ -378,44 +385,44 @@ static void test_ms_storage() ms = prepare_ms(&store, tlli + 0, GPRS_RLCMAC_UL_TBF); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->tlli() == tlli + 0); - ms->set_imsi(imsi1); - OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0); + OSMO_ASSERT(ms_tlli(ms) == tlli + 0); + ms_set_imsi(ms, imsi1); + OSMO_ASSERT(strcmp(ms_imsi(ms), imsi1) == 0); ms_tmp = store.get_ms(tlli + 0); OSMO_ASSERT(ms == ms_tmp); - OSMO_ASSERT(ms->tlli() == tlli + 0); + OSMO_ASSERT(ms_tlli(ms) == tlli + 0); ms_tmp = store.get_ms(0, 0, imsi1); OSMO_ASSERT(ms == ms_tmp); - OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms), imsi1) == 0); ms_tmp = store.get_ms(0, 0, imsi2); OSMO_ASSERT(ms_tmp == NULL); ms = prepare_ms(&store, tlli + 1, GPRS_RLCMAC_UL_TBF); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->tlli() == tlli + 1); - ms->set_imsi(imsi2); - OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0); + OSMO_ASSERT(ms_tlli(ms) == tlli + 1); + ms_set_imsi(ms, imsi2); + OSMO_ASSERT(strcmp(ms_imsi(ms), imsi2) == 0); ms_tmp = store.get_ms(tlli + 1); OSMO_ASSERT(ms == ms_tmp); - OSMO_ASSERT(ms->tlli() == tlli + 1); + OSMO_ASSERT(ms_tlli(ms) == tlli + 1); ms_tmp = store.get_ms(0, 0, imsi1); OSMO_ASSERT(ms_tmp != NULL); OSMO_ASSERT(ms_tmp != ms); ms_tmp = store.get_ms(0, 0, imsi2); OSMO_ASSERT(ms == ms_tmp); - OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms), imsi2) == 0); /* delete ms */ ms = store.get_ms(tlli + 0); OSMO_ASSERT(ms != NULL); ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms); - ms->attach_tbf(ul_tbf); - ms->detach_tbf(ul_tbf); + ms_attach_tbf(ms, ul_tbf); + ms_detach_tbf(ms, ul_tbf); ms = store.get_ms(tlli + 0); OSMO_ASSERT(ms == NULL); ms = store.get_ms(tlli + 1); @@ -424,8 +431,8 @@ static void test_ms_storage() /* delete ms */ ms = store.get_ms(tlli + 1); OSMO_ASSERT(ms != NULL); - ms->attach_tbf(ul_tbf); - ms->detach_tbf(ul_tbf); + ms_attach_tbf(ms, ul_tbf); + ms_detach_tbf(ms, ul_tbf); ms = store.get_ms(tlli + 1); OSMO_ASSERT(ms == NULL); @@ -441,62 +448,49 @@ static void test_ms_timeout() gprs_rlcmac_ul_tbf *ul_tbf; BTS the_bts; GprsMs *ms; - static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN; - - struct MyCallback: public GprsMs::Callback { - virtual void ms_idle(class GprsMs *ms) { - OSMO_ASSERT(ms->is_idle()); - printf(" ms_idle() was called\n"); - last_cb = IS_IDLE; - } - virtual void ms_active(class GprsMs *ms) { - OSMO_ASSERT(!ms->is_idle()); - printf(" ms_active() was called\n"); - last_cb = IS_ACTIVE; - } - } cb; + last_cb = CB_UNKNOWN; printf("=== start %s ===\n", __func__); - ms = new GprsMs(&the_bts, tlli); - ms->set_callback(&cb); - ms->set_timeout(1); + ms = ms_alloc(&the_bts, tlli); + ms_set_callback(ms, &ms_cb); + ms_set_timeout(ms, 1); - OSMO_ASSERT(ms->is_idle()); + OSMO_ASSERT(ms_is_idle(ms)); dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms); ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf); new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms); - OSMO_ASSERT(last_cb == UNKNOWN); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->attach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(last_cb == IS_ACTIVE); + ms_attach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(last_cb == CB_IS_ACTIVE); - last_cb = UNKNOWN; + last_cb = CB_UNKNOWN; - ms->attach_tbf(dl_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(last_cb == UNKNOWN); + ms_attach_tbf(ms, dl_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->detach_tbf(ul_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(last_cb == UNKNOWN); + ms_detach_tbf(ms, ul_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(last_cb == CB_UNKNOWN); - ms->detach_tbf(dl_tbf); - OSMO_ASSERT(!ms->is_idle()); - OSMO_ASSERT(last_cb == UNKNOWN); + ms_detach_tbf(ms, dl_tbf); + OSMO_ASSERT(!ms_is_idle(ms)); + OSMO_ASSERT(last_cb == CB_UNKNOWN); usleep(1100000); osmo_timers_update(); - OSMO_ASSERT(ms->is_idle()); - OSMO_ASSERT(last_cb == IS_IDLE); + OSMO_ASSERT(ms_is_idle(ms)); + OSMO_ASSERT(last_cb == CB_IS_IDLE); - last_cb = UNKNOWN; - delete ms; + last_cb = CB_UNKNOWN; + talloc_free(ms); talloc_free(dl_tbf); talloc_free(ul_tbf); @@ -519,21 +513,21 @@ static void test_ms_cs_selection() bts->cs_downgrade_threshold = 0; bts->cs_adj_lower_limit = 0; - ms = new GprsMs(&the_bts, tlli); + ms = ms_alloc(&the_bts, tlli); - OSMO_ASSERT(ms->is_idle()); + OSMO_ASSERT(ms_is_idle(ms)); dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms); - ms->attach_tbf(dl_tbf); + ms_attach_tbf(ms, dl_tbf); - OSMO_ASSERT(!ms->is_idle()); + OSMO_ASSERT(!ms_is_idle(ms)); - OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3); + OSMO_ASSERT(mcs_chan_code(ms_current_cs_dl(ms)) == 3); bts->cs_downgrade_threshold = 200; - OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2); + OSMO_ASSERT(mcs_chan_code(ms_current_cs_dl(ms)) == 2); talloc_free(dl_tbf); @@ -543,10 +537,10 @@ static void test_ms_cs_selection() static void dump_ms(const GprsMs *ms, const char *pref) { printf("%s MS DL %s/%s, UL %s/%s, mode %s, <%s>\n", pref, - mcs_name(ms->current_cs_dl()), mcs_name(ms->max_cs_dl()), - mcs_name(ms->current_cs_ul()), mcs_name(ms->max_cs_ul()), - mode_name(ms->mode()), - ms->is_idle() ? "IDLE" : "ACTIVE"); + mcs_name(ms_current_cs_dl(ms)), mcs_name(ms_max_cs_dl(ms)), + mcs_name(ms_current_cs_ul(ms)), mcs_name(ms_max_cs_ul(ms)), + mode_name(ms_mode(ms)), + ms_is_idle(ms) ? "IDLE" : "ACTIVE"); } static void test_ms_mcs_mode() @@ -560,48 +554,48 @@ static void test_ms_mcs_mode() printf("=== start %s ===\n", __func__); - ms1 = new GprsMs(&the_bts, tlli); + ms1 = ms_alloc(&the_bts, tlli); dump_ms(ms1, "1: no BTS defaults "); bts->initial_cs_dl = 4; bts->initial_cs_ul = 1; bts->cs_downgrade_threshold = 0; - ms2 = new GprsMs(&the_bts, tlli + 1); + ms2 = ms_alloc(&the_bts, tlli + 1); dump_ms(ms2, "2: with BTS defaults"); dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf); new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms2); - ms2->attach_tbf(dl_tbf); + ms_attach_tbf(ms2, dl_tbf); dump_ms(ms2, "2: after TBF attach "); - ms1->set_mode(EGPRS); + ms_set_mode(ms1, EGPRS); dump_ms(ms1, "1: after mode set "); - ms2->set_mode(EGPRS); + ms_set_mode(ms2, EGPRS); dump_ms(ms2, "2: after mode set "); - ms1->set_current_cs_dl(MCS7); + ms_set_current_cs_dl(ms1, MCS7); dump_ms(ms1, "1: after MCS set "); - ms2->set_current_cs_dl(MCS8); + ms_set_current_cs_dl(ms2, MCS8); dump_ms(ms2, "2: after MCS set "); - ms1->set_mode(EGPRS_GMSK); + ms_set_mode(ms1, EGPRS_GMSK); dump_ms(ms1, "1: after mode set "); - ms2->set_mode(EGPRS_GMSK); + ms_set_mode(ms2, EGPRS_GMSK); dump_ms(ms2, "2: after mode set "); // FIXME: following code triggers ASAN failure: // ms2->detach_tbf(dl_tbf); // dump_ms(ms2, "2: after TBF detach "); - ms1->set_mode(GPRS); + ms_set_mode(ms1, GPRS); dump_ms(ms1, "1: after mode set "); - ms2->set_mode(GPRS); + ms_set_mode(ms2, GPRS); dump_ms(ms2, "2: after mode set "); talloc_free(dl_tbf); diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 1a1dc6f3..e6041a36 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -109,14 +109,14 @@ static void test_tbf_tlli_update() OSMO_ASSERT(dl_tbf != NULL); dl_tbf->update_ms(0x2342, GPRS_RLCMAC_DL_TBF); dl_tbf->set_ta(4); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); OSMO_ASSERT(dl_tbf->ms() == ms); gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(the_bts.bts_data(), ms, 0, false); OSMO_ASSERT(ul_tbf != NULL); ul_tbf->update_ms(0x2342, GPRS_RLCMAC_UL_TBF); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); OSMO_ASSERT(ul_tbf->ms() == ms); OSMO_ASSERT(the_bts.ms_by_tlli(0x2342) == ms); @@ -133,8 +133,8 @@ static void test_tbf_tlli_update() ms_new = the_bts.ms_by_tlli(0x4232); OSMO_ASSERT(ms == ms_new); - OSMO_ASSERT(ms->dl_tbf() == dl_tbf); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); /* Now use the new TLLI for UL */ ul_tbf->update_ms(0x4232, GPRS_RLCMAC_UL_TBF); @@ -143,7 +143,7 @@ static void test_tbf_tlli_update() ms_new = the_bts.ms_by_tlli(0x4232); OSMO_ASSERT(ms_new != NULL); - OSMO_ASSERT(ms_new->ta() == 4); + OSMO_ASSERT(ms_ta(ms_new) == 4); OSMO_ASSERT(ul_tbf->ta() == 4); OSMO_ASSERT(dl_tbf->ta() == 4); @@ -298,25 +298,27 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode) /* Clean up and ensure tbfs are in the correct state */ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE)); - new_tbf = ms->dl_tbf(); + new_tbf = ms_dl_tbf(ms); check_tbf(new_tbf); OSMO_ASSERT(new_tbf != dl_tbf); OSMO_ASSERT(new_tbf->tfi() == 1); check_tbf(dl_tbf); TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE); if (test_mode == TEST_MODE_REVERSE_FREE) { - GprsMs::Guard guard(ms); + ms_ref(ms); tbf_free(new_tbf); - OSMO_ASSERT(ms->dl_tbf() == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); check_tbf(dl_tbf); tbf_free(dl_tbf); + ms_unref(ms); } else { - GprsMs::Guard guard(ms); + ms_ref(ms); tbf_free(dl_tbf); - OSMO_ASSERT(ms->dl_tbf() == new_tbf); + OSMO_ASSERT(ms_dl_tbf(ms) == new_tbf); check_tbf(new_tbf); tbf_free(new_tbf); - OSMO_ASSERT(ms->dl_tbf() == NULL); + OSMO_ASSERT(ms_dl_tbf(ms) == NULL); + ms_unref(ms); } fprintf(stderr, "=== end %s ===\n", __func__); @@ -421,32 +423,33 @@ static void test_tbf_imsi() dl_tbf[0]->update_ms(0xf1000001, GPRS_RLCMAC_DL_TBF); dl_tbf[1]->update_ms(0xf1000002, GPRS_RLCMAC_DL_TBF); - dl_tbf[0]->ms()->set_imsi("001001000000001"); + ms_set_imsi(dl_tbf[0]->ms(), "001001000000001"); ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000001"); OSMO_ASSERT(ms1 != NULL); ms2 = the_bts.ms_store().get_ms(0xf1000001); OSMO_ASSERT(ms2 != NULL); - OSMO_ASSERT(strcmp(ms2->imsi(), "001001000000001") == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000001") == 0); OSMO_ASSERT(ms1 == ms2); /* change the IMSI on TBF 0 */ - dl_tbf[0]->ms()->set_imsi("001001000000002"); + ms_set_imsi(dl_tbf[0]->ms(), "001001000000002"); ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000001"); OSMO_ASSERT(ms1 == NULL); ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002"); OSMO_ASSERT(ms1 != NULL); - OSMO_ASSERT(strcmp(ms2->imsi(), "001001000000002") == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000002") == 0); OSMO_ASSERT(ms1 == ms2); /* use the same IMSI on TBF 1 */ { - GprsMs::Guard guard(ms2); - dl_tbf[1]->ms()->set_imsi("001001000000002"); + ms_ref(ms2); + ms_set_imsi(dl_tbf[1]->ms(), "001001000000002"); ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002"); OSMO_ASSERT(ms1 != NULL); OSMO_ASSERT(ms1 != ms2); - OSMO_ASSERT(strcmp(ms1->imsi(), "001001000000002") == 0); - OSMO_ASSERT(strcmp(ms2->imsi(), "") == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms1), "001001000000002") == 0); + OSMO_ASSERT(strcmp(ms_imsi(ms2), "") == 0); + ms_unref(ms2); } ms2 = the_bts.ms_store().get_ms(0xf1000001); @@ -539,8 +542,8 @@ static void test_tbf_dl_llc_loss() ms = the_bts.ms_store().get_ms(0, 0, imsi); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->dl_tbf() != NULL); - ms->dl_tbf()->set_ta(0); + OSMO_ASSERT(ms_dl_tbf(ms) != NULL); + ms_dl_tbf(ms)->set_ta(0); /* Handle LLC frame 2 */ memset(buf, 2, sizeof(buf)); @@ -549,7 +552,7 @@ static void test_tbf_dl_llc_loss() OSMO_ASSERT(rc >= 0); /* TBF establishment fails (timeout) */ - tbf_free(ms->dl_tbf()); + tbf_free(ms_dl_tbf(ms)); /* Handle LLC frame 3 */ memset(buf, 3, sizeof(buf)); @@ -557,7 +560,7 @@ static void test_tbf_dl_llc_loss() delay_csec, buf, sizeof(buf)); OSMO_ASSERT(rc >= 0); - OSMO_ASSERT(ms->dl_tbf() != NULL); + OSMO_ASSERT(ms_dl_tbf(ms) != NULL); /* Get first BSN */ struct msgb *msg; @@ -572,8 +575,8 @@ static void test_tbf_dl_llc_loss() 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, }; - while (ms->dl_tbf()->have_data()) { - msg = ms->dl_tbf()->create_dl_acked_block(fn += 4, 7); + while (ms_dl_tbf(ms)->have_data()) { + msg = ms_dl_tbf(ms)->create_dl_acked_block(fn += 4, 7); fprintf(stderr, "MSG = %s\n", msgb_hexdump(msg)); if (!msgb_eq_data_print(msg, exp[expected_data - 1], GSM_MACBLOCK_LEN)) fprintf(stderr, "%s failed at %u\n", __func__, expected_data); @@ -742,8 +745,8 @@ static gprs_rlcmac_ul_tbf *puan_urbb_len_issue(BTS *the_bts, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); /* * TS 44.060, B.8.1 @@ -890,8 +893,8 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_spb(BTS *the_bts, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); /* * TS 44.060, B.8.1 @@ -1386,8 +1389,8 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_no_length(BTS *t ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); return ul_tbf; } @@ -1469,8 +1472,8 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_URBB_with_length(BTS ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); return ul_tbf; } @@ -1554,8 +1557,8 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_puan_CRBB(BTS *the_bts, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); return ul_tbf; } @@ -1637,8 +1640,8 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(BTS *the_bts, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); return ul_tbf; } @@ -1655,7 +1658,7 @@ static void send_dl_data(BTS *the_bts, uint32_t tlli, const char *imsi, ms = the_bts->ms_by_imsi(imsi); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->dl_tbf() != NULL); + OSMO_ASSERT(ms_dl_tbf(ms) != NULL); if (imsi[0] && strcmp(imsi, "000") != 0) { ms2 = the_bts->ms_by_tlli(tlli); @@ -1672,7 +1675,7 @@ static void transmit_dl_data(BTS *the_bts, uint32_t tlli, uint32_t *fn, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms); - dl_tbf = ms->dl_tbf(); + dl_tbf = ms_dl_tbf(ms); OSMO_ASSERT(dl_tbf); while (dl_tbf->have_data()) { @@ -1692,7 +1695,7 @@ static inline void print_ta_tlli(const gprs_rlcmac_ul_tbf *ul_tbf, bool print_ms { fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta()); if (print_ms) - fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ul_tbf->ms()->tlli(), ul_tbf->ms()->ta()); + fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms_tlli(ul_tbf->ms()), ms_ta(ul_tbf->ms())); } static void test_tbf_single_phase() @@ -1866,10 +1869,10 @@ static void test_tbf_two_phase() fprintf(stderr, "=== end %s ===\n", __func__); } -static inline void print_ms(const GprsMs *ms, bool old) +static inline void print_ms(GprsMs *ms, bool old) { fprintf(stderr, "%s MS: TLLI = 0x%08x, TA = %d, IMSI = %s, LLC = %zu\n", - old ? "Old" : "New", ms->tlli(), ms->ta(), ms->imsi(), ms->llc_queue()->size()); + old ? "Old" : "New", ms_tlli(ms), ms_ta(ms), ms_imsi(ms), llc_queue_size(ms_llc_queue(ms))); } static void test_tbf_ra_update_rach() @@ -1905,9 +1908,9 @@ static void test_tbf_ra_update_rach() send_control_ack(ul_tbf); /* Make sure the RAU Accept gets sent to the MS */ - OSMO_ASSERT(ms1->llc_queue()->size() == 1); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 1); transmit_dl_data(&the_bts, tlli1, &fn); - OSMO_ASSERT(ms1->llc_queue()->size() == 0); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0); /* Now establish a new TBF for the RA UPDATE COMPLETE (new TLLI) */ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli2, &fn, qta, @@ -1963,8 +1966,8 @@ static void test_tbf_dl_flow_and_rach_two_phase() send_dl_data(&the_bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20); print_ms(ms1, true); - OSMO_ASSERT(ms1->llc_queue()->size() == 2); - dl_tbf = ms1->dl_tbf(); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2); + dl_tbf = ms_dl_tbf(ms1); OSMO_ASSERT(dl_tbf != NULL); /* Get rid of old UL TBF */ @@ -1986,10 +1989,10 @@ static void test_tbf_dl_flow_and_rach_two_phase() OSMO_ASSERT(ms2 == ms); /* A DL TBF should still exist */ - OSMO_ASSERT(ms->dl_tbf()); + OSMO_ASSERT(ms_dl_tbf(ms)); /* No queued packets should be lost */ - OSMO_ASSERT(ms->llc_queue()->size() == 2); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2); fprintf(stderr, "=== end %s ===\n", __func__); } @@ -2022,8 +2025,8 @@ static void test_tbf_dl_flow_and_rach_single_phase() send_dl_data(&the_bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20); print_ms(ms1, true); - OSMO_ASSERT(ms1->llc_queue()->size() == 2); - dl_tbf = ms1->dl_tbf(); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2); + dl_tbf = ms_dl_tbf(ms1); OSMO_ASSERT(dl_tbf != NULL); /* Get rid of old UL TBF */ @@ -2045,10 +2048,10 @@ static void test_tbf_dl_flow_and_rach_single_phase() OSMO_ASSERT(ms1 != ms); /* DL TBF should be removed */ - OSMO_ASSERT(!ms->dl_tbf()); + OSMO_ASSERT(!ms_dl_tbf(ms)); /* No queued packets should be lost */ - OSMO_ASSERT(ms->llc_queue()->size() == 2); + OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2); fprintf(stderr, "=== end %s ===\n", __func__); } @@ -2099,11 +2102,11 @@ static void test_tbf_dl_reuse() /* Transmit all data */ transmit_dl_data(&the_bts, tlli1, &fn); - OSMO_ASSERT(ms1->llc_queue()->size() == 0); - OSMO_ASSERT(ms1->dl_tbf()); - OSMO_ASSERT(ms1->dl_tbf()->state_is(GPRS_RLCMAC_FINISHED)); + 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)); - dl_tbf1 = ms1->dl_tbf(); + dl_tbf1 = ms_dl_tbf(ms1); /* Send some LLC frames */ for (i = 0; i < 10; i++) { @@ -2132,10 +2135,10 @@ static void test_tbf_dl_reuse() ms2 = the_bts.ms_by_tlli(tlli1); OSMO_ASSERT(ms2 == ms1); - OSMO_ASSERT(ms2->dl_tbf()); - OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_ASSIGN)); + OSMO_ASSERT(ms_dl_tbf(ms2)); + OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_ASSIGN)); - dl_tbf2 = ms2->dl_tbf(); + dl_tbf2 = ms_dl_tbf(ms2); OSMO_ASSERT(dl_tbf1 != dl_tbf2); @@ -2144,9 +2147,9 @@ static void test_tbf_dl_reuse() /* Transmit all data */ transmit_dl_data(&the_bts, tlli1, &fn); - OSMO_ASSERT(ms2->llc_queue()->size() == 0); - OSMO_ASSERT(ms2->dl_tbf()); - OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_FINISHED)); + 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)); fprintf(stderr, "=== end %s ===\n", __func__); } @@ -2411,8 +2414,8 @@ static gprs_rlcmac_ul_tbf *tbf_li_decoding(BTS *the_bts, ms = the_bts->ms_by_tlli(tlli); OSMO_ASSERT(ms != NULL); - OSMO_ASSERT(ms->ta() == qta/4); - OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + OSMO_ASSERT(ms_ta(ms) == qta/4); + OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg; egprs3->si = 0; @@ -2799,9 +2802,7 @@ static void egprs_spb_to_normal_validation(BTS *the_bts, OSMO_ASSERT(bsn1 == 0); - dl_tbf->ms()->set_current_cs_dl - (static_cast < enum CodingScheme > - (CS4 + demanded_mcs)); + ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs)); fn = fn_add_blocks(fn, 1); @@ -2831,9 +2832,7 @@ static void egprs_spb_to_normal_validation(BTS *the_bts, OSMO_ASSERT(egprs3->cps == 3); /* Handle (MCS3, MCS3) -> MCS6 case */ - dl_tbf->ms()->set_current_cs_dl - (static_cast < enum CodingScheme > - (CS4 + mcs)); + ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + mcs)); NACK(dl_tbf, 0); @@ -2880,9 +2879,7 @@ static void establish_and_use_egprs_dl_tbf_for_spb(BTS *the_bts, NACK(dl_tbf, 0); - dl_tbf->ms()->set_current_cs_dl - (static_cast < enum CodingScheme > - (CS4 + demanded_mcs)); + ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs)); fn = fn_add_blocks(fn, 1); @@ -2967,9 +2964,7 @@ static void establish_and_use_egprs_dl_tbf_for_retx(BTS *the_bts, NACK(dl_tbf, 1); /* Set the demanded MCS to demanded_mcs */ - dl_tbf->ms()->set_current_cs_dl - (static_cast < enum CodingScheme > - (CS4 + demanded_mcs)); + ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs)); fn = fn_add_blocks(fn, 1); /* Retransmit the first RLC data block with demanded_mcs */ @@ -2994,9 +2989,7 @@ static void establish_and_use_egprs_dl_tbf_for_retx(BTS *the_bts, NACK(dl_tbf, 0); NACK(dl_tbf, 1); - dl_tbf->ms()->set_current_cs_dl - (static_cast < enum CodingScheme > - (CS4 + demanded_mcs)); + ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs)); fn = fn_add_blocks(fn, 1); /* Send first, second RLC data blocks with demanded_mcs */ @@ -3264,8 +3257,8 @@ int main(int argc, char **argv) pcu_vty_init(); /* Initialize shared UL measurements */ - meas.set_link_qual(12); - meas.set_rssi(31); + pcu_l1_meas_set_link_qual(&meas, 12); + pcu_l1_meas_set_rssi(&meas, 31); test_tbf_base(); test_tbf_tlli_update(); diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp index f224146c..bc24b305 100644 --- a/tests/types/TypesTest.cpp +++ b/tests/types/TypesTest.cpp @@ -58,27 +58,27 @@ static void test_llc(void) gprs_llc llc; llc.init(); - OSMO_ASSERT(llc.chunk_size() == 0); - OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN); - OSMO_ASSERT(llc.frame_length() == 0); + OSMO_ASSERT(llc_chunk_size(&llc) == 0); + OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN); + OSMO_ASSERT(llc_frame_length(&llc) == 0); llc.put_frame(data, 2); - OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 2); - OSMO_ASSERT(llc.frame_length() == 2); - OSMO_ASSERT(llc.chunk_size() == 2); + OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 2); + OSMO_ASSERT(llc_frame_length(&llc) == 2); + OSMO_ASSERT(llc_chunk_size(&llc) == 2); OSMO_ASSERT(llc.frame[0] == 1); OSMO_ASSERT(llc.frame[1] == 2); llc.append_frame(&data[3], 1); - OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 3); - OSMO_ASSERT(llc.frame_length() == 3); - OSMO_ASSERT(llc.chunk_size() == 3); + OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 3); + OSMO_ASSERT(llc_frame_length(&llc) == 3); + OSMO_ASSERT(llc_chunk_size(&llc) == 3); /* consume two bytes */ - llc.consume(&out, 1); - OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 3); - OSMO_ASSERT(llc.frame_length() == 3); - OSMO_ASSERT(llc.chunk_size() == 2); + llc_consume_data(&llc, &out, 1); + OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 3); + OSMO_ASSERT(llc_frame_length(&llc) == 3); + OSMO_ASSERT(llc_chunk_size(&llc) == 2); /* check that the bytes are as we expected */ OSMO_ASSERT(llc.frame[0] == 1); @@ -86,9 +86,9 @@ static void test_llc(void) OSMO_ASSERT(llc.frame[2] == 4); /* now fill the frame */ - llc.append_frame(data, llc.remaining_space() - 1); - OSMO_ASSERT(llc.fits_in_current_frame(1)); - OSMO_ASSERT(!llc.fits_in_current_frame(2)); + llc.append_frame(data, llc_remaining_space(&llc) - 1); + OSMO_ASSERT(llc_fits_in_current_frame(&llc, 1)); + OSMO_ASSERT(!llc_fits_in_current_frame(&llc, 2)); } } |