aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bts.cpp51
-rw-r--r--src/bts.h16
-rw-r--r--src/encoding.cpp20
-rw-r--r--src/gprs_ms.c885
-rw-r--r--src/gprs_ms.cpp900
-rw-r--r--src/gprs_ms.h316
-rw-r--r--src/gprs_ms_storage.cpp64
-rw-r--r--src/gprs_ms_storage.h10
-rw-r--r--src/gprs_rlcmac_sched.cpp6
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp32
-rw-r--r--src/llc.cpp30
-rw-r--r--src/llc.h80
-rw-r--r--src/pcu_l1_if.cpp21
-rw-r--r--src/pcu_l1_if.h89
-rw-r--r--src/pcu_utils.h23
-rw-r--r--src/pcu_vty_functions.cpp98
-rw-r--r--src/pdch.cpp58
-rw-r--r--src/tbf.cpp106
-rw-r--r--src/tbf.h54
-rw-r--r--src/tbf_dl.cpp86
-rw-r--r--src/tbf_dl.h18
-rw-r--r--src/tbf_ul.cpp30
-rw-r--r--src/tbf_ul.h30
-rw-r--r--tests/alloc/AllocTest.cpp75
-rw-r--r--tests/app_info/AppInfoTest.cpp4
-rw-r--r--tests/app_info/AppInfoTest.err11
-rw-r--r--tests/edge/EdgeTest.cpp7
-rw-r--r--tests/llc/LlcTest.cpp80
-rw-r--r--tests/ms/MsTest.cpp474
-rw-r--r--tests/tbf/TbfTest.cpp155
-rw-r--r--tests/types/TypesTest.cpp32
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();
+}
diff --git a/src/bts.h b/src/bts.h
index 055b131d..f10542f4 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -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
diff --git a/src/llc.h b/src/llc.h
index 3c2e57a9..72fa62ea 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -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();
+}
diff --git a/src/tbf.h b/src/tbf.h
index c97477bc..4bbfea2b 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -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));
}
}