<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21748">View Change</a></p><div style="white-space:pre-wrap">Approvals:
laforge: Looks good to me, but someone else must approve
pespin: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Convert GprsMS and helpers classes to C<br><br>As we integrate osmo-pcu more and more with libosmocore features, it<br>becomes really hard to use them since libosmocore relies heavily on C<br>specific compilation features, which are not available in old C++<br>compilers (such as designated initializers for complex types in FSMs).<br><br>GprsMs is right now a quite simple object since initial design of<br>osmo-pcu made it optional and most of the logic was placed and stored<br>duplicated in TBF objects. However, that's changing as we introduce more<br>features, with the GprsMS class getting more weight. Hence, let's move<br>it now to be a C struct in order to be able to easily use libosmocore<br>features there, such as FSMs.<br><br>Some helper classes which GprsMs uses are also mostly move to C since<br>they are mostly structs with methods, so there's no point in having<br>duplicated APIs for C++ and C for such simple cases.<br><br>For some more complex classes, like (ul_,dl_)tbf, C API bindings are<br>added where needed so that GprsMs can use functionalitites from that<br>class. Most of those APIs can be kept afterwards and drop the C++ ones<br>since they provide no benefit in general.<br><br>Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c<br>---<br>M src/Makefile.am<br>M src/bts.cpp<br>M src/bts.h<br>M src/encoding.cpp<br>A src/gprs_ms.c<br>D src/gprs_ms.cpp<br>M src/gprs_ms.h<br>M src/gprs_ms_storage.cpp<br>M src/gprs_ms_storage.h<br>M src/gprs_rlcmac_sched.cpp<br>M src/gprs_rlcmac_ts_alloc.cpp<br>M src/llc.cpp<br>M src/llc.h<br>M src/pcu_l1_if.cpp<br>M src/pcu_l1_if.h<br>M src/pcu_utils.h<br>M src/pcu_vty_functions.cpp<br>M src/pdch.cpp<br>M src/tbf.cpp<br>M src/tbf.h<br>M src/tbf_dl.cpp<br>M src/tbf_dl.h<br>M src/tbf_ul.cpp<br>M src/tbf_ul.h<br>M tests/alloc/AllocTest.cpp<br>M tests/app_info/AppInfoTest.cpp<br>M tests/app_info/AppInfoTest.err<br>M tests/edge/EdgeTest.cpp<br>M tests/llc/LlcTest.cpp<br>M tests/ms/MsTest.cpp<br>M tests/tbf/TbfTest.cpp<br>M tests/types/TypesTest.cpp<br>32 files changed, 1,977 insertions(+), 1,920 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index ece372d..386a1f6 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -47,7 +47,7 @@</span><br><span> gprs_rlcmac_sched.cpp \</span><br><span> gprs_rlcmac_meas.cpp \</span><br><span> gprs_rlcmac_ts_alloc.cpp \</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_ms.cpp \</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_ms.c \</span><br><span> gprs_ms_storage.cpp \</span><br><span> gsm_timer.cpp \</span><br><span> pcu_l1_if.cpp \</span><br><span>diff --git a/src/bts.cpp b/src/bts.cpp</span><br><span>index b4f902a..bd0a1d2 100644</span><br><span>--- a/src/bts.cpp</span><br><span>+++ b/src/bts.cpp</span><br><span>@@ -712,7 +712,7 @@</span><br><span> </span><br><span> ms = ms_by_tlli(tlli);</span><br><span> if (ms)</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms);</span><br><span> if (!dl_tbf) {</span><br><span> LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "</span><br><span> "does not exit\n", tlli);</span><br><span>@@ -1140,9 +1140,9 @@</span><br><span> GprsMs *ms;</span><br><span> ms = ms_store().create_ms();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_timeout(osmo_tdef_get(m_bts.T_defs_pcu, -2030, OSMO_TDEF_S, -1));</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ms_class(ms_class);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_egprs_ms_class(egprs_ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_timeout(ms, osmo_tdef_get(m_bts.T_defs_pcu, -2030, OSMO_TDEF_S, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ms_class(ms, ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_egprs_ms_class(ms, egprs_ms_class);</span><br><span> </span><br><span> return ms;</span><br><span> }</span><br><span>@@ -1206,22 +1206,22 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_rlcmac_trx::reserve_slots(enum gprs_rlcmac_tbf_direction dir,</span><br><span style="color: hsl(120, 100%, 40%);">+void bts_trx_reserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir,</span><br><span> uint8_t slots)</span><br><span> {</span><br><span> unsigned i;</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < ARRAY_SIZE(pdch); i += 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_SIZE(trx->pdch); i += 1)</span><br><span> if (slots & (1 << i))</span><br><span style="color: hsl(0, 100%, 40%);">- pdch[i].reserve(dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ trx->pdch[i].reserve(dir);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_rlcmac_trx::unreserve_slots(enum gprs_rlcmac_tbf_direction dir,</span><br><span style="color: hsl(120, 100%, 40%);">+void bts_trx_unreserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir,</span><br><span> uint8_t slots)</span><br><span> {</span><br><span> unsigned i;</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < ARRAY_SIZE(pdch); i += 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_SIZE(trx->pdch); i += 1)</span><br><span> if (slots & (1 << i))</span><br><span style="color: hsl(0, 100%, 40%);">- pdch[i].unreserve(dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ trx->pdch[i].unreserve(dir);</span><br><span> }</span><br><span> </span><br><span> void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul)</span><br><span>@@ -1277,3 +1277,34 @@</span><br><span> bts->bts->set_max_mcs_dl(mcs_dl);</span><br><span> bts->bts->set_max_mcs_ul(mcs_ul);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_bts *bts_data(struct BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return &bts->m_bts;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return bts->ms_by_imsi(imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t bts_max_cs_dl(const struct BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return bts->max_cs_dl();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t bts_max_cs_ul(const struct BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return bts->max_cs_ul();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t bts_max_mcs_dl(const struct BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return bts->max_mcs_dl();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t bts_max_mcs_ul(const struct BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return bts->max_mcs_ul();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/bts.h b/src/bts.h</span><br><span>index 055b131..f10542f 100644</span><br><span>--- a/src/bts.h</span><br><span>+++ b/src/bts.h</span><br><span>@@ -90,15 +90,14 @@</span><br><span> struct BTS *bts;</span><br><span> uint8_t trx_no;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">- void reserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots);</span><br><span style="color: hsl(0, 100%, 40%);">- void unreserve_slots(enum gprs_rlcmac_tbf_direction dir, uint8_t slots);</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span> };</span><br><span> </span><br><span> #ifdef __cplusplus</span><br><span> extern "C" {</span><br><span> #endif</span><br><span style="color: hsl(120, 100%, 40%);">+void bts_trx_reserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots);</span><br><span style="color: hsl(120, 100%, 40%);">+void bts_trx_unreserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint8_t slots);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void bts_update_tbf_ta(const char *p, uint32_t fn, uint8_t trx_no, uint8_t ts, int8_t ta, bool is_rach);</span><br><span> #ifdef __cplusplus</span><br><span> }</span><br><span>@@ -372,10 +371,11 @@</span><br><span> </span><br><span> LListHead<gprs_rlcmac_tbf>& ul_tbfs();</span><br><span> LListHead<gprs_rlcmac_tbf>& dl_tbfs();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_bts m_bts;</span><br><span> private:</span><br><span> int m_cur_fn;</span><br><span> int m_cur_blk_fn;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_rlcmac_bts m_bts;</span><br><span> uint8_t m_max_cs_dl, m_max_cs_ul;</span><br><span> uint8_t m_max_mcs_dl, m_max_mcs_ul;</span><br><span> PollController m_pollController;</span><br><span>@@ -459,11 +459,17 @@</span><br><span> extern "C" {</span><br><span> #endif</span><br><span> void bts_cleanup();</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_bts *bts_data(struct BTS *bts);</span><br><span> struct gprs_rlcmac_bts *bts_main_data();</span><br><span> struct rate_ctr_group *bts_main_data_stats();</span><br><span> struct osmo_stat_item_group *bts_main_data_stat_items();</span><br><span> void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul);</span><br><span> void bts_set_max_mcs(struct gprs_rlcmac_bts *bts, uint8_t mcs_dl, uint8_t mcs_ul);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bts_max_cs_dl(const struct BTS *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bts_max_cs_ul(const struct BTS *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bts_max_mcs_dl(const struct BTS *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bts_max_mcs_ul(const struct BTS *bts);</span><br><span> #ifdef __cplusplus</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/encoding.cpp b/src/encoding.cpp</span><br><span>index a16962a..e7b1fb4 100644</span><br><span>--- a/src/encoding.cpp</span><br><span>+++ b/src/encoding.cpp</span><br><span>@@ -1388,7 +1388,7 @@</span><br><span> delimiter = data_block + *num_chunks;</span><br><span> e_pointer = (*num_chunks ? delimiter - 1 : NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- chunk = llc->chunk_size();</span><br><span style="color: hsl(120, 100%, 40%);">+ chunk = llc_chunk_size(llc);</span><br><span> space = rdbi->data_len - *offset;</span><br><span> </span><br><span> /* if chunk will exceed block limit */</span><br><span>@@ -1402,7 +1402,7 @@</span><br><span> *e_pointer |= 0x02; /* set previous M bit = 1 */</span><br><span> }</span><br><span> /* fill only space */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> /* return data block as message */</span><br><span>@@ -1421,7 +1421,7 @@</span><br><span> if (e_pointer)</span><br><span> *e_pointer |= 0x01;</span><br><span> /* fill space */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> *offset = rdbi->data_len;</span><br><span>@@ -1454,7 +1454,7 @@</span><br><span> rdbi->e = 0; /* 0: extensions present */</span><br><span> // no need to set e_pointer nor increase delimiter</span><br><span> /* fill only space, which is 1 octet less than chunk */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> /* return data block as message */</span><br><span>@@ -1485,7 +1485,7 @@</span><br><span> rdbi->e = 0; /* 0: extensions present */</span><br><span> (*num_chunks)++;</span><br><span> /* copy (rest of) LLC frame to space and reset later */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, chunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, chunk);</span><br><span> if (count_payload)</span><br><span> *count_payload = chunk;</span><br><span> data += chunk;</span><br><span>@@ -1536,7 +1536,7 @@</span><br><span> prev_li = (struct rlc_li_field_egprs *)</span><br><span> (*num_chunks ? delimiter - 1 : NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- chunk = llc->chunk_size();</span><br><span style="color: hsl(120, 100%, 40%);">+ chunk = llc_chunk_size(llc);</span><br><span> space = rdbi->data_len - *offset;</span><br><span> </span><br><span> /* if chunk will exceed block limit */</span><br><span>@@ -1546,7 +1546,7 @@</span><br><span> "only remaining space, and we are done\n",</span><br><span> chunk, space);</span><br><span> /* fill only space */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> /* return data block as message */</span><br><span>@@ -1562,7 +1562,7 @@</span><br><span> "this is a final block, we don't add length "</span><br><span> "header, and we are done\n", chunk, space);</span><br><span> /* fill space */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> *offset = rdbi->data_len;</span><br><span>@@ -1578,7 +1578,7 @@</span><br><span> "to start with an empty chunk\n",</span><br><span> chunk, space);</span><br><span> /* fill space */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, space);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, space);</span><br><span> if (count_payload)</span><br><span> *count_payload = space;</span><br><span> *offset = rdbi->data_len;</span><br><span>@@ -1610,7 +1610,7 @@</span><br><span> prev_li = li;</span><br><span> (*num_chunks)++;</span><br><span> /* copy (rest of) LLC frame to space and reset later */</span><br><span style="color: hsl(0, 100%, 40%);">- llc->consume(data, chunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(llc, data, chunk);</span><br><span> if (count_payload)</span><br><span> *count_payload = chunk;</span><br><span> data += chunk;</span><br><span>diff --git a/src/gprs_ms.c b/src/gprs_ms.c</span><br><span>new file mode 100644</span><br><span>index 0000000..94f69cd</span><br><span>--- /dev/null</span><br><span>+++ b/src/gprs_ms.c</span><br><span>@@ -0,0 +1,885 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* gprs_ms.c</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2015-2020 by Sysmocom s.f.m.c. GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Jacob Erlbeck <jerlbeck@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gprs_ms.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "bts.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "tbf.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "tbf_ul.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gprs_debug.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gprs_codel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "pcu_utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <time.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "coding_scheme.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GPRS_CODEL_SLOW_INTERVAL_MS 4000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern void *tall_pcu_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int64_t now_msec()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timespec ts;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_clock_gettime(CLOCK_MONOTONIC, &ts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (int64_t)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gprs_default_cb_ms_idle(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gprs_default_cb_ms_active(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* do nothing */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gpr_ms_callback gprs_default_cb = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_idle = gprs_default_cb_ms_idle,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_active = gprs_default_cb_ms_active,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_timeout(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *ms = (struct GprsMs *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Timeout for MS object, TLLI = 0x%08x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->timer.data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->timer.data = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int ms_talloc_destructor(struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *ms_alloc(struct BTS *bts, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *ms = talloc_zero(tall_pcu_ctx, struct GprsMs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ms, ms_talloc_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->bts = bts;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->cb = gprs_default_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_ul_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_dl_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ta = GSM48_TA_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->is_idle = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&ms->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&ms->old_tbfs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int codel_interval = LLC_CODEL_USE_DEFAULT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->imsi[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&ms->timer, 0, sizeof(ms->timer));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->timer.cb = ms_timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_init(&ms->llc_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms, GPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->bts)</span><br><span style="color: hsl(120, 100%, 40%);">+ codel_interval = bts_data(ms->bts)->llc_codel_interval_msec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (codel_interval) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (codel_interval == LLC_CODEL_USE_DEFAULT)</span><br><span style="color: hsl(120, 100%, 40%);">+ codel_interval = GPRS_CODEL_SLOW_INTERVAL_MS;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->codel_state = talloc(ms, struct gprs_codel);</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_codel_init(ms->codel_state);</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_codel_set_interval(ms->codel_state, codel_interval);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->last_cs_not_low = now_msec();</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->app_info_pending = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int ms_talloc_destructor(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_item *pos, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", ms_tlli(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_reserved_slots(ms, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_timer_pending(&ms->timer))</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timer_del(&ms->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_set_ms((struct gprs_rlcmac_tbf *)ms->ul_tbf, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ul_tbf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_set_ms((struct gprs_rlcmac_tbf *)ms->dl_tbf, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->dl_tbf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)pos->entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_set_ms(tbf, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_clear(&ms->llc_queue, ms->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cb)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->cb = *cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->cb = gprs_default_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_update_status(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ref > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_is_idle(ms) && !ms->is_idle) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->is_idle = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->cb.ms_idle(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* this can be deleted by now, do not access it */</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_is_idle(ms) && ms->is_idle) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->is_idle = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->cb.ms_active(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *ms_ref(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ref += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_unref(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms->ref >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ref -= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ref == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_status(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_start_timer(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->delay == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->timer.data)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->timer.data = ms_ref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timer_schedule(&ms->timer, ms->delay, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_stop_timer(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->timer.data)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timer_del(&ms->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->timer.data = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->mode = mode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->bts)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (ms->mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GPRS:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_gprs(ms->current_cs_ul)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = mcs_get_gprs_by_num(</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_data(ms->bts)->initial_cs_ul);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_valid(ms->current_cs_ul))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = CS1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_gprs(ms->current_cs_dl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = mcs_get_gprs_by_num(</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_data(ms->bts)->initial_cs_dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_valid(ms->current_cs_dl))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = CS1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ case EGPRS_GMSK:</span><br><span style="color: hsl(120, 100%, 40%);">+ case EGPRS:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_edge(ms->current_cs_ul)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = mcs_get_egprs_by_num(</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_data(ms->bts)->initial_mcs_ul);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_valid(ms->current_cs_ul))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = MCS1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_edge(ms->current_cs_dl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = mcs_get_egprs_by_num(</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_data(ms->bts)->initial_mcs_dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_valid(ms->current_cs_dl))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = MCS1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_attach_ul_tbf(struct GprsMs *ms, struct gprs_rlcmac_ul_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf == tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), tbf_name((struct gprs_rlcmac_tbf *)tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->ul_tbf), &ms->old_tbfs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ul_tbf = tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_stop_timer(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_attach_dl_tbf(struct GprsMs *ms, struct gprs_rlcmac_dl_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf == tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), tbf_name((struct gprs_rlcmac_tbf *)tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->dl_tbf), &ms->old_tbfs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->dl_tbf = tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_stop_timer(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_dl_tbf(ms, as_dl_tbf(tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_ul_tbf(ms, as_ul_tbf(tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf == (struct gprs_rlcmac_tbf *)(ms->ul_tbf)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ul_tbf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (tbf == (struct gprs_rlcmac_tbf *)(ms->dl_tbf)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->dl_tbf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ bool found = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_item *pos, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_tbf *tmp_tbf = (struct gprs_rlcmac_tbf *)pos->entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tmp_tbf == tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_del(&pos->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Protect against recursive calls via set_ms() */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!found)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), tbf_name(tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf_ms(tbf) == ms)</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_set_ms(tbf, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->dl_tbf && !ms->ul_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_reserved_slots(ms, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_tlli(ms) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_start_timer(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_status(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_reset(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Clearing MS object, TLLI: 0x%08x, IMSI: '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms_imsi(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_stop_timer(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_dl_tlli = ms->tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_ul_tlli = ms->tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->imsi[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_merge_old_ms(struct GprsMs *ms, struct GprsMs *old_ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(old_ms != ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strlen(ms_imsi(ms)) == 0 && strlen(ms_imsi(old_ms)) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_strlcpy(ms->imsi, ms_imsi(old_ms), sizeof(ms->imsi));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_ms_class(ms) && ms_ms_class(old_ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ms_class(ms, ms_ms_class(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_egprs_ms_class(ms) && ms_egprs_ms_class(old_ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_egprs_ms_class(ms, ms_egprs_ms_class(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_move_and_merge(&ms->llc_queue, &old_ms->llc_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_reset(old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(old_ms != ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Clean up the old MS object */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: Use timer? */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_ul_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms), T_MAX))</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_dl_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms), T_MAX))</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_merge_old_ms(ms, old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_tlli(struct GprsMs *ms, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tlli == ms->tlli || tlli == ms->new_ul_tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tlli != ms->new_dl_tlli) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "not yet confirmed\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_ul_tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI: 0x%08x -> 0x%08x, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "already confirmed partly\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->tlli, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_dl_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_ul_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tlli == ms->tlli || tlli == ms->new_dl_tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tlli != ms->new_ul_tlli) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The MS has not sent a message with the new TLLI, which may</span><br><span style="color: hsl(120, 100%, 40%);">+ * happen according to the spec [TODO: add reference]. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "partly confirmed\n", tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Use the network's idea of TLLI as candidate, this does not</span><br><span style="color: hsl(120, 100%, 40%);">+ * change the result value of tlli() */</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_dl_tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_dl_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->new_ul_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_imsi(struct GprsMs *ms, const char *imsi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!imsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_ERROR, "Expected IMSI!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (imsi[0] && strlen(imsi) < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI '%s'!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(imsi, ms->imsi) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI = 0x%08x, IMSI '%s' -> '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms->imsi, imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *old_ms = bts_ms_by_imsi(ms->bts, imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if we are going to store a different MS object with already</span><br><span style="color: hsl(120, 100%, 40%);">+ existing IMSI. This is probably a bug in code calling this function,</span><br><span style="color: hsl(120, 100%, 40%);">+ since it should take care of this explicitly */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (old_ms) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We cannot find ms->ms by IMSI since we know that it has a</span><br><span style="color: hsl(120, 100%, 40%);">+ * different IMSI */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(old_ms != ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPMS(ms, DRLCMAC, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ "IMSI '%s' was already assigned to another "</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS object: TLLI = 0x%08x, that IMSI will be removed\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ imsi, ms_tlli(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_merge_and_clear_ms(ms, old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_strlcpy(ms->imsi, imsi, sizeof(ms->imsi));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_ta(struct GprsMs *ms, uint8_t ta_)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ta_ == ms->ta)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (gsm48_ta_is_valid(ta_)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI = 0x%08x, TA %d -> %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms->ta, ta_);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ta = ta_;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS object, TLLI = 0x%08x, invalid TA %d rejected (old "</span><br><span style="color: hsl(120, 100%, 40%);">+ "value %d kept)\n", ms_tlli(ms), ta_, ms->ta);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_class_ == ms->ms_class)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI = 0x%08x, MS class %d -> %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms->ms_class, ms_class_);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->ms_class = ms_class_;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_class_ == ms->egprs_ms_class)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Modifying MS object, TLLI = 0x%08x, EGPRS MS class %d -> %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms->egprs_ms_class, ms_class_);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->egprs_ms_class = ms_class_;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bts_max_mcs_ul(ms->bts) || !bts_max_mcs_dl(ms->bts)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPMS(ms, DRLCMAC, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Avoid enabling EGPRS because use of MCS is disabled: ul=%u dl=%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_max_mcs_ul(ms->bts), bts_max_mcs_dl(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts))) &&</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts))) &&</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_mode(ms) != EGPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms, EGPRS_GMSK);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms, EGPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPMS(ms, DRLCMAC, LOGL_INFO, "Enabled EGPRS, mode %s\n", mode_name(ms_mode(ms)));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_bts *bts_;</span><br><span style="color: hsl(120, 100%, 40%);">+ int64_t now;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme max_cs_dl = ms_max_cs_dl(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(max_cs_dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_ = bts_data(ms->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (error_rate < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ now = now_msec();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: Check for TBF direction */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: Support different CS values for UL and DL */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->nack_rate_dl = error_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (error_rate > bts_->cs_adj_upper_limit) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mcs_chan_code(ms->current_cs_dl) > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_dec_kind(&ms->current_cs_dl, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACDL, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS (IMSI %s): High error rate %d%%, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "reducing CS level to %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_imsi(ms), error_rate, mcs_name(ms->current_cs_dl));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->last_cs_not_low = now;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (error_rate < bts_->cs_adj_lower_limit) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->current_cs_dl < max_cs_dl) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (now - ms->last_cs_not_low > 1000) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_inc_kind(&ms->current_cs_dl, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACDL, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS (IMSI %s): Low error rate %d%%, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "increasing DL CS level to %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_imsi(ms), error_rate,</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_dl));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->last_cs_not_low = now;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACDL, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS (IMSI %s): Low error rate %d%%, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "ignored (within blocking period)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_imsi(ms), error_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACDL, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "MS (IMSI %s): Medium error rate %d%%, ignored\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_imsi(ms), error_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->last_cs_not_low = now;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms->bts != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mcs_is_gprs(ms->current_cs_ul)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bts_max_cs_ul(ms->bts)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CS4;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_gprs_by_num(bts_max_cs_ul(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_edge(ms->current_cs_ul))</span><br><span style="color: hsl(120, 100%, 40%);">+ return UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bts_max_mcs_ul(ms->bts))</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (bts_max_cs_ul(ms->bts))</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_gprs_by_num(bts_max_cs_ul(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return MCS4;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_dl = scheme;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms->bts != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mcs_is_gprs(ms->current_cs_dl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bts_max_cs_dl(ms->bts)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CS4;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_gprs_by_num(bts_max_cs_dl(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mcs_is_edge(ms->current_cs_dl))</span><br><span style="color: hsl(120, 100%, 40%);">+ return UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bts_max_mcs_dl(ms->bts))</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (bts_max_cs_dl(ms->bts))</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcs_get_gprs_by_num(bts_max_cs_dl(ms->bts));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return MCS4;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_update_cs_ul(struct GprsMs *ms, const struct pcu_l1_meas *meas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_bts *bts_;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme max_cs_ul = ms_max_cs_ul(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int old_link_qual;</span><br><span style="color: hsl(120, 100%, 40%);">+ int low;</span><br><span style="color: hsl(120, 100%, 40%);">+ int high;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme new_cs_ul = ms->current_cs_ul;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t current_cs = mcs_chan_code(ms->current_cs_ul);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_ = bts_data(ms->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!max_cs_ul) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "max_cs_ul cannot be derived (current UL CS: %s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_ul));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->current_cs_ul) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Unable to update UL (M)CS because it's not set: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_ul));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!meas->have_link_qual) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Unable to update UL (M)CS %s because we don't have link quality measurements.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_ul));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mcs_is_gprs(ms->current_cs_ul)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (current_cs >= MAX_GPRS_CS)</span><br><span style="color: hsl(120, 100%, 40%);">+ current_cs = MAX_GPRS_CS - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ low = bts_->cs_lqual_ranges[current_cs].low;</span><br><span style="color: hsl(120, 100%, 40%);">+ high = bts_->cs_lqual_ranges[current_cs].high;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (mcs_is_edge(ms->current_cs_ul)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (current_cs >= MAX_EDGE_MCS)</span><br><span style="color: hsl(120, 100%, 40%);">+ current_cs = MAX_EDGE_MCS - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ low = bts_->mcs_lqual_ranges[current_cs].low;</span><br><span style="color: hsl(120, 100%, 40%);">+ high = bts_->mcs_lqual_ranges[current_cs].high;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_ul));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* To avoid rapid changes of the coding scheme, we also take</span><br><span style="color: hsl(120, 100%, 40%);">+ * the old link quality value into account (if present). */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_link_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ old_link_qual = ms->l1_meas.link_qual;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ old_link_qual = meas->link_qual;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->link_qual < low && old_link_qual < low)</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_dec_kind(&new_cs_ul, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (meas->link_qual > high && old_link_qual > high &&</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul < max_cs_ul)</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_inc_kind(&new_cs_ul, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->current_cs_ul != new_cs_ul) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPMS(ms, DRLCMACMEAS, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Link quality %ddB (old %ddB) left window [%d, %d], "</span><br><span style="color: hsl(120, 100%, 40%);">+ "modifying uplink CS level: %s -> %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->link_qual, old_link_qual,</span><br><span style="color: hsl(120, 100%, 40%);">+ low, high,</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms->current_cs_ul), mcs_name(new_cs_ul));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_cs_ul = new_cs_ul;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_cs_ul(ms, meas);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_rssi)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_rssi(&ms->l1_meas, meas->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_bto)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_bto(&ms->l1_meas, meas->bto);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_ber)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ber(&ms->l1_meas, meas->ber);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_link_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_link_qual(&ms->l1_meas, meas->link_qual);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_ms_rx_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_rx_qual(&ms->l1_meas, meas->ms_rx_qual);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_ms_c_value)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_c_value(&ms->l1_meas, meas->ms_c_value);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_ms_sign_var)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_sign_var(&ms->l1_meas, meas->ms_sign_var);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->have_ms_i_level) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_SIZE(meas->ts); ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (meas->ts[i].have_ms_i_level)</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_i_level(&ms->l1_meas, i, meas->ts[i].ms_i_level);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.ts[i].have_ms_i_level = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme cs = ms->current_cs_dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t unencoded_octets;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms->bts)</span><br><span style="color: hsl(120, 100%, 40%);">+ return cs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ unencoded_octets = llc_queue_octets(&ms->llc_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If the DL TBF is active, add number of unencoded chunk octets */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ unencoded_octets += llc_chunk_size(tbf_llc((struct gprs_rlcmac_tbf *)ms->dl_tbf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* There are many unencoded octets, don't reduce */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (unencoded_octets >= bts_data(ms->bts)->cs_downgrade_threshold)</span><br><span style="color: hsl(120, 100%, 40%);">+ return cs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* RF conditions are good, don't reduce */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->nack_rate_dl < bts_data(ms->bts)->cs_adj_lower_limit)</span><br><span style="color: hsl(120, 100%, 40%);">+ return cs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The throughput would probably be better if the CS level was reduced */</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_dec_kind(&cs, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cs == CS2)</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_dec_kind(&cs, ms_mode(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return cs;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ms_first_common_ts(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t ms_dl_slots(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t slots = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return slots;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t ms_ul_slots(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t slots = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->dl_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->ul_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return slots;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t ms_current_pacch_slots(const struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t slots = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bool is_dl_active = ms->dl_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ bool is_ul_active = ms->ul_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!is_dl_active && !is_ul_active)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* see TS 44.060, 8.1.1.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is_dl_active && !is_ul_active)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots = tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (!is_dl_active && is_ul_active)</span><br><span style="color: hsl(120, 100%, 40%);">+ slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf) &</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Assume a multislot class 1 device */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: For class 2 devices, this could be removed */</span><br><span style="color: hsl(120, 100%, 40%);">+ slots = pcu_lsb(slots);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return slots;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ul_slots, uint8_t dl_slots)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->current_trx) {</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_dl_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_ul_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_dl_slots = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_ul_slots = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->current_trx = trx;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (trx) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_dl_slots = dl_slots;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_ul_slots = ul_slots;</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_dl_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->reserved_ul_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (dir) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GPRS_RLCMAC_DL_TBF: return (struct gprs_rlcmac_tbf *)ms->dl_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GPRS_RLCMAC_UL_TBF: return (struct gprs_rlcmac_tbf *)ms->ul_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp</span><br><span>deleted file mode 100644</span><br><span>index c891cdf..0000000</span><br><span>--- a/src/gprs_ms.cpp</span><br><span>+++ /dev/null</span><br><span>@@ -1,900 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/* gprs_ms.cpp</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH</span><br><span style="color: hsl(0, 100%, 40%);">- * Author: Jacob Erlbeck <jerlbeck@sysmocom.de></span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(0, 100%, 40%);">- * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(0, 100%, 40%);">- * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(0, 100%, 40%);">- * of the License, or (at your option) any later version.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(0, 100%, 40%);">- * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(0, 100%, 40%);">- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(0, 100%, 40%);">- * GNU General Public License for more details.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(0, 100%, 40%);">- * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(0, 100%, 40%);">- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "gprs_ms.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "bts.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "tbf.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "tbf_ul.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "gprs_debug.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "gprs_codel.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "pcu_utils.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <time.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-extern "C" {</span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/talloc.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/utils.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/timer.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/logging.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include "coding_scheme.h"</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define GPRS_CODEL_SLOW_INTERVAL_MS 4000</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-extern void *tall_pcu_ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int64_t now_msec()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct timespec ts;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_clock_gettime(CLOCK_MONOTONIC, &ts);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return int64_t(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct GprsMsDefaultCallback: public GprsMs::Callback {</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *) {}</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static GprsMsDefaultCallback gprs_default_cb;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-GprsMs::Guard::Guard(GprsMs *ms) :</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms(ms ? ms->ref() : NULL)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-GprsMs::Guard::~Guard()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ms)</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms->unref();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-bool GprsMs::Guard::is_idle() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_ms)</span><br><span style="color: hsl(0, 100%, 40%);">- return true;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return !m_ms->m_ul_tbf && !m_ms->m_dl_tbf && m_ms->m_ref == 1;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::timeout(void *priv_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs *ms = static_cast<GprsMs *>(priv_);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Timeout for MS object, TLLI = 0x%08x\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->tlli());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->m_timer.data) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms->m_timer.data = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- ms->unref();</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-GprsMs::GprsMs(BTS *bts, uint32_t tlli) :</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts(bts),</span><br><span style="color: hsl(0, 100%, 40%);">- m_cb(&gprs_default_cb),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ul_tbf(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_tbf(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- m_tlli(tlli),</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_ul_tlli(GSM_RESERVED_TMSI),</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_dl_tlli(GSM_RESERVED_TMSI),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ta(GSM48_TA_INVALID),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms_class(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_egprs_ms_class(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul(UNKNOWN),</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl(UNKNOWN),</span><br><span style="color: hsl(0, 100%, 40%);">- m_is_idle(true),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ref(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_list(this),</span><br><span style="color: hsl(0, 100%, 40%);">- m_delay(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_nack_rate_dl(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_dl_slots(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_ul_slots(0),</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- m_codel_state(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- m_mode(GPRS),</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_ctrl_msg(0)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int codel_interval = LLC_CODEL_USE_DEFAULT;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_imsi[0] = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">- memset(&m_timer, 0, sizeof(m_timer));</span><br><span style="color: hsl(0, 100%, 40%);">- m_timer.cb = GprsMs::timeout;</span><br><span style="color: hsl(0, 100%, 40%);">- m_llc_queue.init();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- set_mode(m_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_bts)</span><br><span style="color: hsl(0, 100%, 40%);">- codel_interval = m_bts->bts_data()->llc_codel_interval_msec;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (codel_interval) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (codel_interval == LLC_CODEL_USE_DEFAULT)</span><br><span style="color: hsl(0, 100%, 40%);">- codel_interval = GPRS_CODEL_SLOW_INTERVAL_MS;</span><br><span style="color: hsl(0, 100%, 40%);">- m_codel_state = talloc(this, struct gprs_codel);</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_codel_init(m_codel_state);</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_codel_set_interval(m_codel_state, codel_interval);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- m_last_cs_not_low = now_msec();</span><br><span style="color: hsl(0, 100%, 40%);">- app_info_pending = false;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-GprsMs::~GprsMs()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf> *pos, *tmp;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", tlli());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- set_reserved_slots(NULL, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (osmo_timer_pending(&m_timer))</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_timer_del(&m_timer);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_ul_tbf->set_ms(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- m_ul_tbf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_tbf->set_ms(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_tbf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_safe(pos, tmp, &m_old_tbfs)</span><br><span style="color: hsl(0, 100%, 40%);">- pos->entry()->set_ms(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_llc_queue.clear(m_bts);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void* GprsMs::operator new(size_t size)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- static void *tall_ms_ctx = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- if (!tall_ms_ctx)</span><br><span style="color: hsl(0, 100%, 40%);">- tall_ms_ctx = talloc_named_const(tall_pcu_ctx, 0, __PRETTY_FUNCTION__);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return talloc_size(tall_ms_ctx, size);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::operator delete(void* p)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(p);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-GprsMs *GprsMs::ref()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- m_ref += 1;</span><br><span style="color: hsl(0, 100%, 40%);">- return this;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::unref()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(m_ref >= 0);</span><br><span style="color: hsl(0, 100%, 40%);">- m_ref -= 1;</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ref == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- update_status();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::start_timer()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_delay == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_timer.data)</span><br><span style="color: hsl(0, 100%, 40%);">- m_timer.data = ref();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_timer_schedule(&m_timer, m_delay, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::stop_timer()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_timer.data)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_timer_del(&m_timer);</span><br><span style="color: hsl(0, 100%, 40%);">- m_timer.data = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- unref();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_mode(enum mcs_kind mode)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- m_mode = mode;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_bts)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (m_mode) {</span><br><span style="color: hsl(0, 100%, 40%);">- case GPRS:</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_gprs(m_current_cs_ul)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul = mcs_get_gprs_by_num(</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->bts_data()->initial_cs_ul);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_valid(m_current_cs_ul))</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul = CS1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_gprs(m_current_cs_dl)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl = mcs_get_gprs_by_num(</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->bts_data()->initial_cs_dl);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_valid(m_current_cs_dl))</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl = CS1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- case EGPRS_GMSK:</span><br><span style="color: hsl(0, 100%, 40%);">- case EGPRS:</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_edge(m_current_cs_ul)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul = mcs_get_egprs_by_num(</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->bts_data()->initial_mcs_ul);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_valid(m_current_cs_ul))</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul = MCS1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_edge(m_current_cs_dl)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl = mcs_get_egprs_by_num(</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->bts_data()->initial_mcs_dl);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_valid(m_current_cs_dl))</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl = MCS1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf->direction == GPRS_RLCMAC_DL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- attach_dl_tbf(as_dl_tbf(tbf));</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- attach_ul_tbf(as_ul_tbf(tbf));</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf == tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), tbf->name());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- Guard guard(this);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- llist_add_tail(&m_ul_tbf->ms_list(), &m_old_tbfs);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_ul_tbf = tbf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- stop_timer();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf == tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), tbf->name());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- Guard guard(this);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- llist_add_tail(&m_dl_tbf->ms_list(), &m_old_tbfs);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_tbf = tbf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- stop_timer();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf == static_cast<gprs_rlcmac_tbf *>(m_ul_tbf)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_ul_tbf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (tbf == static_cast<gprs_rlcmac_tbf *>(m_dl_tbf)) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_tbf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- bool found = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf> *pos, *tmp;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_safe(pos, tmp, &m_old_tbfs) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (pos->entry() == tbf) {</span><br><span style="color: hsl(0, 100%, 40%);">- llist_del(pos);</span><br><span style="color: hsl(0, 100%, 40%);">- found = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Protect against recursive calls via set_ms() */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!found)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), tbf->name());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf->ms() == this)</span><br><span style="color: hsl(0, 100%, 40%);">- tbf->set_ms(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_dl_tbf && !m_ul_tbf) {</span><br><span style="color: hsl(0, 100%, 40%);">- set_reserved_slots(NULL, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tlli() != 0)</span><br><span style="color: hsl(0, 100%, 40%);">- start_timer();</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- update_status();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::update_status()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ref > 0)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_idle() && !m_is_idle) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_is_idle = true;</span><br><span style="color: hsl(0, 100%, 40%);">- m_cb->ms_idle(this);</span><br><span style="color: hsl(0, 100%, 40%);">- /* this can be deleted by now, do not access it */</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!is_idle() && m_is_idle) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_is_idle = false;</span><br><span style="color: hsl(0, 100%, 40%);">- m_cb->ms_active(this);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::reset()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Clearing MS object, TLLI: 0x%08x, IMSI: '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), imsi());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- stop_timer();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_dl_tlli = m_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_ul_tlli = m_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- m_imsi[0] = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::merge_old_ms(GprsMs *old_ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(old_ms != this);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (strlen(imsi()) == 0 && strlen(old_ms->imsi()) != 0)</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_strlcpy(m_imsi, old_ms->imsi(), sizeof(m_imsi));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms_class() && old_ms->ms_class())</span><br><span style="color: hsl(0, 100%, 40%);">- set_ms_class(old_ms->ms_class());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!egprs_ms_class() && old_ms->egprs_ms_class())</span><br><span style="color: hsl(0, 100%, 40%);">- set_egprs_ms_class(old_ms->egprs_ms_class());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_llc_queue.move_and_merge(&old_ms->m_llc_queue);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- old_ms->reset();</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::merge_and_clear_ms(GprsMs *old_ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(old_ms != this);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard_old(old_ms);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Clean up the old MS object */</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: Use timer? */</span><br><span style="color: hsl(0, 100%, 40%);">- if (old_ms->ul_tbf() && !old_ms->ul_tbf()->timers_pending(T_MAX))</span><br><span style="color: hsl(0, 100%, 40%);">- tbf_free(old_ms->ul_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- if (old_ms->dl_tbf() && !old_ms->dl_tbf()->timers_pending(T_MAX))</span><br><span style="color: hsl(0, 100%, 40%);">- tbf_free(old_ms->dl_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- merge_old_ms(old_ms);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_tlli(uint32_t tlli)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tlli == m_tlli || tlli == m_new_ul_tlli)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tlli != m_new_dl_tlli) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, "</span><br><span style="color: hsl(0, 100%, 40%);">- "not yet confirmed\n",</span><br><span style="color: hsl(0, 100%, 40%);">- this->tlli(), tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_ul_tlli = tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI: 0x%08x -> 0x%08x, "</span><br><span style="color: hsl(0, 100%, 40%);">- "already confirmed partly\n",</span><br><span style="color: hsl(0, 100%, 40%);">- m_tlli, tlli);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_tlli = tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_dl_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_ul_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-bool GprsMs::confirm_tlli(uint32_t tlli)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tlli == m_tlli || tlli == m_new_dl_tlli)</span><br><span style="color: hsl(0, 100%, 40%);">- return false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tlli != m_new_ul_tlli) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* The MS has not sent a message with the new TLLI, which may</span><br><span style="color: hsl(0, 100%, 40%);">- * happen according to the spec [TODO: add reference]. */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, "</span><br><span style="color: hsl(0, 100%, 40%);">- "partly confirmed\n", tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- /* Use the network's idea of TLLI as candidate, this does not</span><br><span style="color: hsl(0, 100%, 40%);">- * change the result value of tlli() */</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_dl_tlli = tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- return false;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_tlli = tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_dl_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(0, 100%, 40%);">- m_new_ul_tlli = GSM_RESERVED_TMSI;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return true;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_imsi(const char *imsi)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (!imsi) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_ERROR, "Expected IMSI!\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (imsi[0] && strlen(imsi) < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI '%s'!\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcmp(imsi, m_imsi) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI = 0x%08x, IMSI '%s' -> '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), m_imsi, imsi);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs *old_ms = m_bts->ms_store().get_ms(0, 0, imsi);</span><br><span style="color: hsl(0, 100%, 40%);">- /* Check if we are going to store a different MS object with already</span><br><span style="color: hsl(0, 100%, 40%);">- existing IMSI. This is probably a bug in code calling this function,</span><br><span style="color: hsl(0, 100%, 40%);">- since it should take care of this explicitly */</span><br><span style="color: hsl(0, 100%, 40%);">- if (old_ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* We cannot find m_ms by IMSI since we know that it has a</span><br><span style="color: hsl(0, 100%, 40%);">- * different IMSI */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(old_ms != this);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPMS(this, DRLCMAC, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "IMSI '%s' was already assigned to another "</span><br><span style="color: hsl(0, 100%, 40%);">- "MS object: TLLI = 0x%08x, that IMSI will be removed\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi, old_ms->tlli());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- merge_and_clear_ms(old_ms);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_strlcpy(m_imsi, imsi, sizeof(m_imsi));</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_ta(uint8_t ta_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ta_ == m_ta)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (gsm48_ta_is_valid(ta_)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI = 0x%08x, TA %d -> %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), m_ta, ta_);</span><br><span style="color: hsl(0, 100%, 40%);">- m_ta = ta_;</span><br><span style="color: hsl(0, 100%, 40%);">- } else</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "MS object, TLLI = 0x%08x, invalid TA %d rejected (old "</span><br><span style="color: hsl(0, 100%, 40%);">- "value %d kept)\n", tlli(), ta_, m_ta);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_ms_class(uint8_t ms_class_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms_class_ == m_ms_class)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI = 0x%08x, MS class %d -> %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), m_ms_class, ms_class_);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms_class = ms_class_;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_egprs_ms_class(uint8_t ms_class_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms_class_ == m_egprs_ms_class)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMAC, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Modifying MS object, TLLI = 0x%08x, EGPRS MS class %d -> %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- tlli(), m_egprs_ms_class, ms_class_);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_egprs_ms_class = ms_class_;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_bts->max_mcs_ul() || !m_bts->max_mcs_dl()) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPMS(this, DRLCMAC, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "Avoid enabling EGPRS because use of MCS is disabled: ul=%u dl=%u\n",</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->max_mcs_ul(), m_bts->max_mcs_dl());</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(m_bts->max_mcs_ul())) &&</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_is_edge_gmsk(mcs_get_egprs_by_num(m_bts->max_mcs_dl())) &&</span><br><span style="color: hsl(0, 100%, 40%);">- mode() != EGPRS)</span><br><span style="color: hsl(0, 100%, 40%);">- {</span><br><span style="color: hsl(0, 100%, 40%);">- set_mode(EGPRS_GMSK);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- set_mode(EGPRS);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPMS(this, DRLCMAC, LOGL_INFO, "Enabled EGPRS, mode %s\n", mode_name(mode()));</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_rlcmac_bts *bts_data;</span><br><span style="color: hsl(0, 100%, 40%);">- int64_t now;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme max_cs_dl = this->max_cs_dl();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(max_cs_dl);</span><br><span style="color: hsl(0, 100%, 40%);">- bts_data = m_bts->bts_data();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (error_rate < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- now = now_msec();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: Check for TBF direction */</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: Support different CS values for UL and DL */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_nack_rate_dl = error_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (error_rate > bts_data->cs_adj_upper_limit) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (mcs_chan_code(m_current_cs_dl) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_dec_kind(&m_current_cs_dl, mode());</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACDL, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "MS (IMSI %s): High error rate %d%%, "</span><br><span style="color: hsl(0, 100%, 40%);">- "reducing CS level to %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi(), error_rate, mcs_name(m_current_cs_dl));</span><br><span style="color: hsl(0, 100%, 40%);">- m_last_cs_not_low = now;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (error_rate < bts_data->cs_adj_lower_limit) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_current_cs_dl < max_cs_dl) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (now - m_last_cs_not_low > 1000) {</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_inc_kind(&m_current_cs_dl, mode());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACDL, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "MS (IMSI %s): Low error rate %d%%, "</span><br><span style="color: hsl(0, 100%, 40%);">- "increasing DL CS level to %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi(), error_rate,</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_dl));</span><br><span style="color: hsl(0, 100%, 40%);">- m_last_cs_not_low = now;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACDL, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "MS (IMSI %s): Low error rate %d%%, "</span><br><span style="color: hsl(0, 100%, 40%);">- "ignored (within blocking period)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi(), error_rate);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACDL, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "MS (IMSI %s): Medium error rate %d%%, ignored\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi(), error_rate);</span><br><span style="color: hsl(0, 100%, 40%);">- m_last_cs_not_low = now;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum CodingScheme GprsMs::max_cs_ul() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(m_bts != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (mcs_is_gprs(m_current_cs_ul)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_bts->max_cs_ul()) {</span><br><span style="color: hsl(0, 100%, 40%);">- return CS4;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_gprs_by_num(m_bts->max_cs_ul());</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_edge(m_current_cs_ul))</span><br><span style="color: hsl(0, 100%, 40%);">- return UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_bts->max_mcs_ul())</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_egprs_by_num(m_bts->max_mcs_ul());</span><br><span style="color: hsl(0, 100%, 40%);">- else if (m_bts->max_cs_ul())</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_gprs_by_num(m_bts->max_cs_ul());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return MCS4;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_current_cs_dl(enum CodingScheme scheme)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_dl = scheme;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum CodingScheme GprsMs::max_cs_dl() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(m_bts != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (mcs_is_gprs(m_current_cs_dl)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_bts->max_cs_dl()) {</span><br><span style="color: hsl(0, 100%, 40%);">- return CS4;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_gprs_by_num(m_bts->max_cs_dl());</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mcs_is_edge(m_current_cs_dl))</span><br><span style="color: hsl(0, 100%, 40%);">- return UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_bts->max_mcs_dl())</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_egprs_by_num(m_bts->max_mcs_dl());</span><br><span style="color: hsl(0, 100%, 40%);">- else if (m_bts->max_cs_dl())</span><br><span style="color: hsl(0, 100%, 40%);">- return mcs_get_gprs_by_num(m_bts->max_cs_dl());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return MCS4;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::update_cs_ul(const pcu_l1_meas *meas)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_rlcmac_bts *bts_data;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme max_cs_ul = this->max_cs_ul();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int old_link_qual;</span><br><span style="color: hsl(0, 100%, 40%);">- int low;</span><br><span style="color: hsl(0, 100%, 40%);">- int high;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme new_cs_ul = m_current_cs_ul;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t current_cs = mcs_chan_code(m_current_cs_ul);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bts_data = m_bts->bts_data();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!max_cs_ul) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "max_cs_ul cannot be derived (current UL CS: %s)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_ul));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_current_cs_ul) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Unable to update UL (M)CS because it's not set: %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_ul));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!meas->have_link_qual) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Unable to update UL (M)CS %s because we don't have link quality measurements.\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_ul));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (mcs_is_gprs(m_current_cs_ul)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (current_cs >= MAX_GPRS_CS)</span><br><span style="color: hsl(0, 100%, 40%);">- current_cs = MAX_GPRS_CS - 1;</span><br><span style="color: hsl(0, 100%, 40%);">- low = bts_data->cs_lqual_ranges[current_cs].low;</span><br><span style="color: hsl(0, 100%, 40%);">- high = bts_data->cs_lqual_ranges[current_cs].high;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (mcs_is_edge(m_current_cs_ul)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (current_cs >= MAX_EDGE_MCS)</span><br><span style="color: hsl(0, 100%, 40%);">- current_cs = MAX_EDGE_MCS - 1;</span><br><span style="color: hsl(0, 100%, 40%);">- low = bts_data->mcs_lqual_ranges[current_cs].low;</span><br><span style="color: hsl(0, 100%, 40%);">- high = bts_data->mcs_lqual_ranges[current_cs].high;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRLCMACMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_ul));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* To avoid rapid changes of the coding scheme, we also take</span><br><span style="color: hsl(0, 100%, 40%);">- * the old link quality value into account (if present). */</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_l1_meas.have_link_qual)</span><br><span style="color: hsl(0, 100%, 40%);">- old_link_qual = m_l1_meas.link_qual;</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- old_link_qual = meas->link_qual;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->link_qual < low && old_link_qual < low)</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_dec_kind(&new_cs_ul, mode());</span><br><span style="color: hsl(0, 100%, 40%);">- else if (meas->link_qual > high && old_link_qual > high &&</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul < max_cs_ul)</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_inc_kind(&new_cs_ul, mode());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_current_cs_ul != new_cs_ul) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPMS(this, DRLCMACMEAS, LOGL_INFO,</span><br><span style="color: hsl(0, 100%, 40%);">- "Link quality %ddB (old %ddB) left window [%d, %d], "</span><br><span style="color: hsl(0, 100%, 40%);">- "modifying uplink CS level: %s -> %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- meas->link_qual, old_link_qual,</span><br><span style="color: hsl(0, 100%, 40%);">- low, high,</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_current_cs_ul), mcs_name(new_cs_ul));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_cs_ul = new_cs_ul;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::update_l1_meas(const pcu_l1_meas *meas)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- update_cs_ul(meas);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_rssi)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_rssi(meas->rssi);</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_bto)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_bto(meas->bto);</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_ber)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_ber(meas->ber);</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_link_qual)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_link_qual(meas->link_qual);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_ms_rx_qual)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_ms_rx_qual(meas->ms_rx_qual);</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_ms_c_value)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_ms_c_value(meas->ms_c_value);</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_ms_sign_var)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_ms_sign_var(meas->ms_sign_var);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->have_ms_i_level) {</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < ARRAY_SIZE(meas->ts); ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (meas->ts[i].have_ms_i_level)</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.set_ms_i_level(i, meas->ts[i].ms_i_level);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- m_l1_meas.ts[i].have_ms_i_level = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum CodingScheme GprsMs::current_cs_dl() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme cs = m_current_cs_dl;</span><br><span style="color: hsl(0, 100%, 40%);">- size_t unencoded_octets;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!m_bts)</span><br><span style="color: hsl(0, 100%, 40%);">- return cs;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- unencoded_octets = m_llc_queue.octets();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* If the DL TBF is active, add number of unencoded chunk octets */</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- unencoded_octets += m_dl_tbf->m_llc.chunk_size();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* There are many unencoded octets, don't reduce */</span><br><span style="color: hsl(0, 100%, 40%);">- if (unencoded_octets >= m_bts->bts_data()->cs_downgrade_threshold)</span><br><span style="color: hsl(0, 100%, 40%);">- return cs;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* RF conditions are good, don't reduce */</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_nack_rate_dl < m_bts->bts_data()->cs_adj_lower_limit)</span><br><span style="color: hsl(0, 100%, 40%);">- return cs;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* The throughput would probably be better if the CS level was reduced */</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_dec_kind(&cs, mode());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (cs == CS2)</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_dec_kind(&cs, mode());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return cs;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int GprsMs::first_common_ts() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- return m_dl_tbf->first_common_ts;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ul_tbf->first_common_ts;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-uint8_t GprsMs::dl_slots() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t slots = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- slots |= m_dl_tbf->dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- slots |= m_ul_tbf->dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return slots;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-uint8_t GprsMs::ul_slots() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t slots = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_dl_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- slots |= m_dl_tbf->ul_slots();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ul_tbf)</span><br><span style="color: hsl(0, 100%, 40%);">- slots |= m_ul_tbf->ul_slots();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return slots;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-uint8_t GprsMs::current_pacch_slots() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t slots = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool is_dl_active = m_dl_tbf && m_dl_tbf->is_tfi_assigned();</span><br><span style="color: hsl(0, 100%, 40%);">- bool is_ul_active = m_ul_tbf && m_ul_tbf->is_tfi_assigned();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!is_dl_active && !is_ul_active)</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* see TS 44.060, 8.1.1.2.2 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_dl_active && !is_ul_active)</span><br><span style="color: hsl(0, 100%, 40%);">- slots = m_dl_tbf->dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">- else if (!is_dl_active && is_ul_active)</span><br><span style="color: hsl(0, 100%, 40%);">- slots = m_ul_tbf->ul_slots();</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- slots = m_ul_tbf->ul_slots() & m_dl_tbf->dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Assume a multislot class 1 device */</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: For class 2 devices, this could be removed */</span><br><span style="color: hsl(0, 100%, 40%);">- slots = pcu_lsb(slots);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return slots;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMs::set_reserved_slots(gprs_rlcmac_trx *trx,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ul_slots, uint8_t dl_slots)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_current_trx) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx->unreserve_slots(GPRS_RLCMAC_DL_TBF,</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_dl_slots);</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx->unreserve_slots(GPRS_RLCMAC_UL_TBF,</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_ul_slots);</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_dl_slots = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_ul_slots = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx = trx;</span><br><span style="color: hsl(0, 100%, 40%);">- if (trx) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_dl_slots = dl_slots;</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_ul_slots = ul_slots;</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx->reserve_slots(GPRS_RLCMAC_DL_TBF,</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_dl_slots);</span><br><span style="color: hsl(0, 100%, 40%);">- m_current_trx->reserve_slots(GPRS_RLCMAC_UL_TBF,</span><br><span style="color: hsl(0, 100%, 40%);">- m_reserved_ul_slots);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-gprs_rlcmac_tbf *GprsMs::tbf(enum gprs_rlcmac_tbf_direction dir) const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- switch (dir) {</span><br><span style="color: hsl(0, 100%, 40%);">- case GPRS_RLCMAC_DL_TBF: return m_dl_tbf;</span><br><span style="color: hsl(0, 100%, 40%);">- case GPRS_RLCMAC_UL_TBF: return m_ul_tbf;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span>diff --git a/src/gprs_ms.h b/src/gprs_ms.h</span><br><span>index 8b8940b..ade3f3b 100644</span><br><span>--- a/src/gprs_ms.h</span><br><span>+++ b/src/gprs_ms.h</span><br><span>@@ -1,6 +1,6 @@</span><br><span> /* gprs_ms.h</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2015-2020 by Sysmocom s.f.m.c. GmbH</span><br><span> * Author: Jacob Erlbeck <jerlbeck@sysmocom.de></span><br><span> *</span><br><span> * This program is free software; you can redistribute it and/or</span><br><span>@@ -22,22 +22,23 @@</span><br><span> </span><br><span> struct gprs_codel;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include "cxx_linuxlist.h"</span><br><span> #include "llc.h"</span><br><span> #include "tbf.h"</span><br><span> #include "tbf_ul.h"</span><br><span> #include "tbf_dl.h"</span><br><span> #include "pcu_l1_if.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> extern "C" {</span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/timer.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/gsm/protocol/gsm_23_003.h></span><br><span style="color: hsl(0, 100%, 40%);">- #include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- #include "coding_scheme.h"</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_23_003.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "coding_scheme.h"</span><br><span> </span><br><span> #include <stdint.h></span><br><span> #include <stddef.h></span><br><span>@@ -45,268 +46,207 @@</span><br><span> </span><br><span> struct BTS;</span><br><span> struct gprs_rlcmac_trx;</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class GprsMs {</span><br><span style="color: hsl(0, 100%, 40%);">-public:</span><br><span style="color: hsl(0, 100%, 40%);">- struct Callback {</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *) = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *) = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- class Guard {</span><br><span style="color: hsl(0, 100%, 40%);">- public:</span><br><span style="color: hsl(0, 100%, 40%);">- Guard(GprsMs *ms);</span><br><span style="color: hsl(0, 100%, 40%);">- ~Guard();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool is_idle() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- private:</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs * const m_ms;</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs(BTS *bts, uint32_t tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ~GprsMs();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void set_callback(Callback *cb) {m_cb = cb;}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void merge_and_clear_ms(GprsMs *old_ms);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;}</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;}</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_tbf *tbf(enum gprs_rlcmac_tbf_direction dir) const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t tlli() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_tlli(uint32_t tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- bool confirm_tlli(uint32_t tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- bool check_tlli(uint32_t tlli);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void reset();</span><br><span style="color: hsl(0, 100%, 40%);">- enum mcs_kind mode() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_mode(enum mcs_kind mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- const char *imsi() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_imsi(const char *imsi);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ta() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_ta(uint8_t ta);</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ms_class() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t egprs_ms_class() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_ms_class(uint8_t ms_class);</span><br><span style="color: hsl(0, 100%, 40%);">- void set_egprs_ms_class(uint8_t ms_class);</span><br><span style="color: hsl(0, 100%, 40%);">- void set_current_cs_dl(enum CodingScheme scheme);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme current_cs_ul() const;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme current_cs_dl() const;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme max_cs_ul() const;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme max_cs_dl() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int first_common_ts() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t dl_slots() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ul_slots() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t reserved_dl_slots() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t reserved_ul_slots() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t current_pacch_slots() const;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_trx *current_trx() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void set_reserved_slots(gprs_rlcmac_trx *trx,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ul_slots, uint8_t dl_slots);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_llc_queue *llc_queue();</span><br><span style="color: hsl(0, 100%, 40%);">- const gprs_llc_queue *llc_queue() const;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_codel *codel_state() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void set_timeout(unsigned secs);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void attach_tbf(gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- void attach_dl_tbf(gprs_rlcmac_dl_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void detach_tbf(gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void update_error_rate(gprs_rlcmac_tbf *tbf, int percent);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool is_idle() const;</span><br><span style="color: hsl(0, 100%, 40%);">- bool need_dl_tbf() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void* operator new(size_t num);</span><br><span style="color: hsl(0, 100%, 40%);">- void operator delete(void* p);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs>& list() {return this->m_list;}</span><br><span style="color: hsl(0, 100%, 40%);">- const LListHead<GprsMs>& list() const {return this->m_list;}</span><br><span style="color: hsl(0, 100%, 40%);">- const LListHead<gprs_rlcmac_tbf>& old_tbfs() const {return m_old_tbfs;}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void update_l1_meas(const pcu_l1_meas *meas);</span><br><span style="color: hsl(0, 100%, 40%);">- const pcu_l1_meas* l1_meas() const {return &m_l1_meas;};</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned nack_rate_dl() const;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned dl_ctrl_msg() const;</span><br><span style="color: hsl(0, 100%, 40%);">- void update_dl_ctrl_msg();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* internal use */</span><br><span style="color: hsl(0, 100%, 40%);">- static void timeout(void *priv_);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool app_info_pending;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-protected:</span><br><span style="color: hsl(0, 100%, 40%);">- void merge_old_ms(GprsMs *old_ms);</span><br><span style="color: hsl(0, 100%, 40%);">- void update_status();</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs *ref();</span><br><span style="color: hsl(0, 100%, 40%);">- void unref();</span><br><span style="color: hsl(0, 100%, 40%);">- void start_timer();</span><br><span style="color: hsl(0, 100%, 40%);">- void stop_timer();</span><br><span style="color: hsl(0, 100%, 40%);">- void update_cs_ul(const pcu_l1_meas*);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-private:</span><br><span style="color: hsl(0, 100%, 40%);">- BTS *m_bts;</span><br><span style="color: hsl(0, 100%, 40%);">- Callback * m_cb;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_ul_tbf *m_ul_tbf;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_dl_tbf *m_dl_tbf;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf> m_old_tbfs;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t m_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t m_new_ul_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t m_new_dl_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* store IMSI for look-up and PCH retransmission */</span><br><span style="color: hsl(0, 100%, 40%);">- char m_imsi[OSMO_IMSI_BUF_SIZE];</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t m_ta;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t m_ms_class;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t m_egprs_ms_class;</span><br><span style="color: hsl(0, 100%, 40%);">- /* current coding scheme */</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme m_current_cs_ul;</span><br><span style="color: hsl(0, 100%, 40%);">- enum CodingScheme m_current_cs_dl;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_llc_queue m_llc_queue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool m_is_idle;</span><br><span style="color: hsl(0, 100%, 40%);">- int m_ref;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> m_list;</span><br><span style="color: hsl(0, 100%, 40%);">- struct osmo_timer_list m_timer;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned m_delay;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int64_t m_last_cs_not_low;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas m_l1_meas;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned m_nack_rate_dl;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t m_reserved_dl_slots;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t m_reserved_ul_slots;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_trx *m_current_trx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_codel *m_codel_state;</span><br><span style="color: hsl(0, 100%, 40%);">- enum mcs_kind m_mode;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned m_dl_ctrl_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+struct gpr_ms_callback {</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*ms_idle)(struct GprsMs *);</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*ms_active)(struct GprsMs *);</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline bool GprsMs::is_idle() const</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list; /* list of all GprsMs */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gpr_ms_callback cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool app_info_pending;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct BTS *bts;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_ul_tbf *ul_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_dl_tbf *dl_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head old_tbfs; /* list of gprs_rlcmac_tbf */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t new_ul_tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t new_dl_tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* store IMSI for look-up and PCH retransmission */</span><br><span style="color: hsl(120, 100%, 40%);">+ char imsi[OSMO_IMSI_BUF_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ta;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ms_class;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t egprs_ms_class;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* current coding scheme */</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme current_cs_ul;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum CodingScheme current_cs_dl;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_llc_queue llc_queue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bool is_idle;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ref;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_timer_list timer;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned delay;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int64_t last_cs_not_low;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct pcu_l1_meas l1_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned nack_rate_dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t reserved_dl_slots;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t reserved_ul_slots;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_trx *current_trx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_codel *codel_state;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum mcs_kind mode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned dl_ctrl_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *ms_alloc(struct BTS *bts, uint32_t tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ms_first_common_ts(const struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ul_slots, uint8_t dl_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *ms_ref(struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_unref(struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_ta(struct GprsMs *ms, uint8_t ta_);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t ms_current_pacch_slots(const struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_tlli(struct GprsMs *ms, uint32_t tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_imsi(struct GprsMs *ms, const char *imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir);</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gprs_rlcmac_ul_tbf *ms_ul_tbf(const struct GprsMs *ms) {return ms->ul_tbf;}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gprs_rlcmac_dl_tbf *ms_dl_tbf(const struct GprsMs *ms) {return ms->dl_tbf;}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool ms_is_idle(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return !m_ul_tbf && !m_dl_tbf && !m_ref && llist_empty(&m_old_tbfs);</span><br><span style="color: hsl(120, 100%, 40%);">+ return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline bool GprsMs::need_dl_tbf() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gprs_llc_queue *ms_llc_queue(struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- if (dl_tbf() != NULL && dl_tbf()->state_is_not(GPRS_RLCMAC_WAIT_RELEASE))</span><br><span style="color: hsl(120, 100%, 40%);">+ return &ms->llc_queue;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool ms_need_dl_tbf(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_dl_tbf(ms) != NULL &&</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_state((const struct gprs_rlcmac_tbf *)ms_dl_tbf(ms)) != GPRS_RLCMAC_WAIT_RELEASE)</span><br><span> return false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return llc_queue()->size() > 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ return llc_queue_size(ms_llc_queue(ms)) > 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint32_t GprsMs::tlli() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint32_t ms_tlli(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_new_ul_tlli != GSM_RESERVED_TMSI)</span><br><span style="color: hsl(0, 100%, 40%);">- return m_new_ul_tlli;</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_tlli != GSM_RESERVED_TMSI)</span><br><span style="color: hsl(0, 100%, 40%);">- return m_tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->new_ul_tlli != GSM_RESERVED_TMSI)</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->new_ul_tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->tlli != GSM_RESERVED_TMSI)</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->tlli;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return m_new_dl_tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->new_dl_tlli;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline bool GprsMs::check_tlli(uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool ms_check_tlli(struct GprsMs *ms, uint32_t tlli)</span><br><span> {</span><br><span> return tlli != GSM_RESERVED_TMSI &&</span><br><span style="color: hsl(0, 100%, 40%);">- (tlli == m_tlli || tlli == m_new_ul_tlli || tlli == m_new_dl_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ (tlli == ms->tlli || tlli == ms->new_ul_tlli || tlli == ms->new_dl_tlli);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline const char *GprsMs::imsi() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *ms_imsi(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_imsi;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->imsi;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t GprsMs::ta() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t ms_ta(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ta;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->ta;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t GprsMs::ms_class() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t ms_ms_class(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms_class;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->ms_class;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t GprsMs::egprs_ms_class() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t ms_egprs_ms_class(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_egprs_ms_class;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->egprs_ms_class;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline enum CodingScheme GprsMs::current_cs_ul() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline enum CodingScheme ms_current_cs_ul(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_current_cs_ul;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->current_cs_ul;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline enum mcs_kind GprsMs::mode() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline enum mcs_kind ms_mode(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->mode;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline void GprsMs::set_timeout(unsigned secs)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ms_set_timeout(struct GprsMs *ms, unsigned secs)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- m_delay = secs;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->delay = secs;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline gprs_llc_queue *GprsMs::llc_queue()</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gprs_codel *ms_codel_state(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return &m_llc_queue;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->codel_state;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline const gprs_llc_queue *GprsMs::llc_queue() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline unsigned ms_nack_rate_dl(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return &m_llc_queue;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->nack_rate_dl;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline gprs_codel *GprsMs::codel_state() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline unsigned ms_dl_ctrl_msg(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_codel_state;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->dl_ctrl_msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline unsigned GprsMs::nack_rate_dl() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ms_update_dl_ctrl_msg(struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_nack_rate_dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->dl_ctrl_msg++;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline unsigned GprsMs::dl_ctrl_msg() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t ms_reserved_dl_slots(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_dl_ctrl_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->reserved_dl_slots;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline void GprsMs::update_dl_ctrl_msg()</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t ms_reserved_ul_slots(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- m_dl_ctrl_msg++;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->reserved_ul_slots;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t GprsMs::reserved_dl_slots() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gprs_rlcmac_trx *ms_current_trx(const struct GprsMs *ms)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_reserved_dl_slots;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t GprsMs::reserved_ul_slots() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return m_reserved_ul_slots;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-inline gprs_rlcmac_trx *GprsMs::current_trx() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return m_current_trx;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms->current_trx;</span><br><span> }</span><br><span> </span><br><span> #define LOGPMS(ms, category, level, fmt, args...) \</span><br><span> LOGP(category, level, "MS(TLLI=0x%08x, IMSI=%s, TA=%" PRIu8 ", %" PRIu8 "/%" PRIu8 ",%s%s) " fmt, \</span><br><span style="color: hsl(0, 100%, 40%);">- (ms)->tlli(), (ms)->imsi(), (ms)->ta(), (ms)->ms_class(), (ms)->egprs_ms_class(), \</span><br><span style="color: hsl(0, 100%, 40%);">- (ms)->ul_tbf() ? " UL": "", \</span><br><span style="color: hsl(0, 100%, 40%);">- (ms)->dl_tbf() ? " DL": "", \</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms), ms_imsi(ms), ms_ta(ms), ms_ms_class(ms), ms_egprs_ms_class(ms), \</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ul_tbf(ms) ? " UL": "", \</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms) ? " DL": "", \</span><br><span> ## args)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp</span><br><span>index 73570b3..6d5b09e 100644</span><br><span>--- a/src/gprs_ms_storage.cpp</span><br><span>+++ b/src/gprs_ms_storage.cpp</span><br><span>@@ -31,9 +31,29 @@</span><br><span> </span><br><span> #define GPRS_UNDEFINED_IMSI "000"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_storage_ms_idle_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_del(&ms->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->bts)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->bts->stat_item_add(STAT_MS_PRESENT, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_is_idle(ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_storage_ms_active_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Nothing to do */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gpr_ms_callback ms_storage_ms_cb = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_idle = ms_storage_ms_idle_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_active = ms_storage_ms_active_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> GprsMsStorage::GprsMsStorage(BTS *bts) :</span><br><span> m_bts(bts)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&m_list);</span><br><span> }</span><br><span> </span><br><span> GprsMsStorage::~GprsMsStorage()</span><br><span>@@ -43,40 +63,26 @@</span><br><span> </span><br><span> void GprsMsStorage::cleanup()</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> *pos, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head *pos, *tmp;</span><br><span> </span><br><span> llist_for_each_safe(pos, tmp, &m_list) {</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs *ms = pos->entry();</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_callback(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ms_idle(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *ms = llist_entry(pos, typeof(*ms), list);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_callback(ms, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_storage_ms_idle_cb(ms);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMsStorage::ms_idle(class GprsMs *ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- llist_del(&ms->list());</span><br><span style="color: hsl(0, 100%, 40%);">- if (m_bts)</span><br><span style="color: hsl(0, 100%, 40%);">- m_bts->stat_item_add(STAT_MS_PRESENT, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->is_idle())</span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void GprsMsStorage::ms_active(class GprsMs *ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- /* Nothing to do */</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> GprsMs *GprsMsStorage::get_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi) const</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head *tmp;</span><br><span> GprsMs *ms;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> *pos;</span><br><span> </span><br><span> if (tlli != GSM_RESERVED_TMSI || old_tlli != GSM_RESERVED_TMSI) {</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each(pos, &m_list) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms = pos->entry();</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->check_tlli(tlli))</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each(tmp, &m_list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = llist_entry(tmp, typeof(*ms), list);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_check_tlli(ms, tlli))</span><br><span> return ms;</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->check_tlli(old_tlli))</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_check_tlli(ms, old_tlli))</span><br><span> return ms;</span><br><span> }</span><br><span> }</span><br><span>@@ -84,9 +90,9 @@</span><br><span> /* not found by TLLI */</span><br><span> </span><br><span> if (imsi && imsi[0] && strcmp(imsi, GPRS_UNDEFINED_IMSI) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each(pos, &m_list) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms = pos->entry();</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcmp(imsi, ms->imsi()) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each(tmp, &m_list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = llist_entry(tmp, typeof(*ms), list);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(imsi, ms_imsi(ms)) == 0)</span><br><span> return ms;</span><br><span> }</span><br><span> }</span><br><span>@@ -98,10 +104,10 @@</span><br><span> {</span><br><span> GprsMs *ms;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(m_bts, GSM_RESERVED_TMSI);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(m_bts, GSM_RESERVED_TMSI);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_callback(this);</span><br><span style="color: hsl(0, 100%, 40%);">- llist_add(&ms->list(), &m_list);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_callback(ms, &ms_storage_ms_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add(&ms->list, &m_list);</span><br><span> if (m_bts)</span><br><span> m_bts->stat_item_add(STAT_MS_PRESENT, 1);</span><br><span> </span><br><span>diff --git a/src/gprs_ms_storage.h b/src/gprs_ms_storage.h</span><br><span>index 35062f3..af49688 100644</span><br><span>--- a/src/gprs_ms_storage.h</span><br><span>+++ b/src/gprs_ms_storage.h</span><br><span>@@ -21,28 +21,24 @@</span><br><span> #pragma once</span><br><span> </span><br><span> #include "gprs_ms.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "cxx_linuxlist.h"</span><br><span> #include "tbf.h"</span><br><span> #include <stdint.h></span><br><span> #include <stddef.h></span><br><span> </span><br><span> struct BTS;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class GprsMsStorage : public GprsMs::Callback {</span><br><span style="color: hsl(120, 100%, 40%);">+class GprsMsStorage {</span><br><span> public:</span><br><span> GprsMsStorage(BTS *bts);</span><br><span> ~GprsMsStorage();</span><br><span> </span><br><span> void cleanup();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *);</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> GprsMs *get_ms(uint32_t tlli, uint32_t old_tlli = GSM_RESERVED_TMSI, const char *imsi = NULL) const;</span><br><span> GprsMs *create_ms();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- const LListHead<GprsMs>& ms_list() const {return m_list;}</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct llist_head* ms_list() const {return &m_list;}</span><br><span> private:</span><br><span> BTS *m_bts;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> m_list;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head m_list; /* list of struct GprsMs */</span><br><span> };</span><br><span>diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp</span><br><span>index 70d8237..caf121f 100644</span><br><span>--- a/src/gprs_rlcmac_sched.cpp</span><br><span>+++ b/src/gprs_rlcmac_sched.cpp</span><br><span>@@ -234,7 +234,7 @@</span><br><span> "message at RTS for %s (TRX=%d, TS=%d)\n",</span><br><span> tbf_name(tbf), trx, ts);</span><br><span> /* Updates the dl ctrl msg counter for ms */</span><br><span style="color: hsl(0, 100%, 40%);">- tbf->ms()->update_dl_ctrl_msg();</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_dl_ctrl_msg(tbf->ms());</span><br><span> return msg;</span><br><span> }</span><br><span> </span><br><span>@@ -342,7 +342,7 @@</span><br><span> pdch->next_dl_tfi = (prio_tfi + 1) & 31;</span><br><span> /* generate DL data block */</span><br><span> msg = prio_tbf->create_dl_acked_block(fn, ts, req_mcs_kind);</span><br><span style="color: hsl(0, 100%, 40%);">- *is_egprs = prio_tbf->ms()->mode() != GPRS;</span><br><span style="color: hsl(120, 100%, 40%);">+ *is_egprs = ms_mode(prio_tbf->ms()) != GPRS;</span><br><span> }</span><br><span> </span><br><span> return msg;</span><br><span>@@ -463,7 +463,7 @@</span><br><span> * only be able to read USF if dl block uses GMSK</span><br><span> * (CS1-4, MCS1-4)</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- if (req_mcs_kind == EGPRS && usf_tbf->ms()->mode() != EGPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (req_mcs_kind == EGPRS && ms_mode(usf_tbf->ms()) != EGPRS)</span><br><span> req_mcs_kind = EGPRS_GMSK;</span><br><span> } else {</span><br><span> usf = USF_UNUSED;</span><br><span>diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp</span><br><span>index 9551c59..1ef32f2 100644</span><br><span>--- a/src/gprs_rlcmac_ts_alloc.cpp</span><br><span>+++ b/src/gprs_rlcmac_ts_alloc.cpp</span><br><span>@@ -245,8 +245,8 @@</span><br><span> unsigned ts;</span><br><span> </span><br><span> /* We must use the TRX currently actively used by an MS */</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms && ms->current_trx())</span><br><span style="color: hsl(0, 100%, 40%);">- return ms->current_trx()->trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms && ms_current_trx(ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms_current_trx(ms)->trx_no;</span><br><span> </span><br><span> if (use_trx >= 0 && use_trx < 8)</span><br><span> return use_trx;</span><br><span>@@ -320,8 +320,8 @@</span><br><span> use_trx = trx->trx_no;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (use_trx == -1 && ms->current_trx())</span><br><span style="color: hsl(0, 100%, 40%);">- use_trx = ms->current_trx()->trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (use_trx == -1 && ms_current_trx(ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ use_trx = ms_current_trx(ms)->trx_no;</span><br><span> </span><br><span> tfi = bts->tfi_find_free(dir, &trx_no, use_trx);</span><br><span> if (tfi < 0)</span><br><span>@@ -357,7 +357,7 @@</span><br><span> const char *mask_reason = NULL;</span><br><span> const GprsMs *ms = ms_;</span><br><span> const gprs_rlcmac_tbf *tbf = tbf_;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_trx *trx = ms->current_trx();</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_rlcmac_trx *trx = ms_current_trx(ms);</span><br><span> </span><br><span> LOGPAL(tbf, "A", single, use_trx, LOGL_DEBUG, "Alloc start\n");</span><br><span> </span><br><span>@@ -370,10 +370,10 @@</span><br><span> if (!trx)</span><br><span> trx = &bts->trx[trx_no];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_slots = ms->reserved_dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">- ul_slots = ms->reserved_ul_slots();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_slots = ms_reserved_dl_slots(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_slots = ms_reserved_ul_slots(ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ts = ms->first_common_ts();</span><br><span style="color: hsl(120, 100%, 40%);">+ ts = ms_first_common_ts(ms);</span><br><span> </span><br><span> if (ts >= 0) {</span><br><span> mask_reason = "need to reuse TS";</span><br><span>@@ -420,7 +420,7 @@</span><br><span> tbf_->trx = trx;</span><br><span> /* the only one TS is the common TS */</span><br><span> tbf_->first_ts = tbf_->first_common_ts = ts;</span><br><span style="color: hsl(0, 100%, 40%);">- ms_->set_reserved_slots(trx, 1 << ts, 1 << ts);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_reserved_slots(ms_, trx, 1 << ts, 1 << ts);</span><br><span> </span><br><span> tbf_->upgrade_to_multislot = 0;</span><br><span> bts->bts->do_rate_ctr_inc(CTR_TBF_ALLOC_ALGO_A);</span><br><span>@@ -774,11 +774,11 @@</span><br><span> {</span><br><span> char slot_info[9] = { 0 };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (res_ul_slots == ms->reserved_ul_slots() && res_dl_slots == ms->reserved_dl_slots())</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res_ul_slots == ms_reserved_ul_slots(ms) && res_dl_slots == ms_reserved_dl_slots(ms))</span><br><span> return;</span><br><span> </span><br><span> /* The reserved slots have changed, update the MS */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_reserved_slots(trx, res_ul_slots, res_dl_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_reserved_slots(ms, trx, res_ul_slots, res_dl_slots);</span><br><span> </span><br><span> ts_format(slot_info, dl_slots, ul_slots);</span><br><span> LOGP(DRLCMAC, LOGL_DEBUG, "- Reserved DL/UL slots: (TS=0)\"%s\"(TS=7)\n", slot_info);</span><br><span>@@ -867,10 +867,10 @@</span><br><span> return -EINVAL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_slots = ms->reserved_dl_slots();</span><br><span style="color: hsl(0, 100%, 40%);">- ul_slots = ms->reserved_ul_slots();</span><br><span style="color: hsl(0, 100%, 40%);">- first_common_ts = ms->first_common_ts();</span><br><span style="color: hsl(0, 100%, 40%);">- trx = ms->current_trx();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_slots = ms_reserved_dl_slots(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_slots = ms_reserved_ul_slots(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ first_common_ts = ms_first_common_ts(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ trx = ms_current_trx(ms);</span><br><span> </span><br><span> /* Step 2a: Find usable TRX and TFI */</span><br><span> tfi = tfi_find_free(bts->bts, trx, ms, tbf->direction, use_trx, &trx_no);</span><br><span>@@ -884,7 +884,7 @@</span><br><span> trx = &bts->trx[trx_no];</span><br><span> </span><br><span> if (!dl_slots || !ul_slots) {</span><br><span style="color: hsl(0, 100%, 40%);">- rc = find_multi_slots(trx, ms->ms_class(), &ul_slots, &dl_slots);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = find_multi_slots(trx, ms_ms_class(ms), &ul_slots, &dl_slots);</span><br><span> if (rc < 0)</span><br><span> return rc;</span><br><span> }</span><br><span>diff --git a/src/llc.cpp b/src/llc.cpp</span><br><span>index e2d01c2..d1122f5 100644</span><br><span>--- a/src/llc.cpp</span><br><span>+++ b/src/llc.cpp</span><br><span>@@ -97,12 +97,12 @@</span><br><span> return true;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_llc_queue::init()</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_init(struct gprs_llc_queue *q)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- INIT_LLIST_HEAD(&m_queue);</span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_size = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_octets = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- m_avg_queue_delay = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&q->m_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_octets = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_avg_queue_delay = 0;</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -122,21 +122,21 @@</span><br><span> msgb_enqueue(&m_queue, llc_msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_llc_queue::clear(BTS *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_clear(struct gprs_llc_queue *q, struct BTS *bts)</span><br><span> {</span><br><span> struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- while ((msg = msgb_dequeue(&m_queue))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((msg = msgb_dequeue(&q->m_queue))) {</span><br><span> if (bts)</span><br><span> bts->do_rate_ctr_inc(CTR_LLC_FRAME_DROPPED);</span><br><span> msgb_free(msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_size = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_octets = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_octets = 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_llc_queue::move_and_merge(gprs_llc_queue *o)</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o)</span><br><span> {</span><br><span> struct msgb *msg, *msg1 = NULL, *msg2 = NULL;</span><br><span> struct llist_head new_queue;</span><br><span>@@ -146,7 +146,7 @@</span><br><span> </span><br><span> while (1) {</span><br><span> if (msg1 == NULL)</span><br><span style="color: hsl(0, 100%, 40%);">- msg1 = msgb_dequeue(&m_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+ msg1 = msgb_dequeue(&q->m_queue);</span><br><span> </span><br><span> if (msg2 == NULL)</span><br><span> msg2 = msgb_dequeue(&o->m_queue);</span><br><span>@@ -178,15 +178,15 @@</span><br><span> queue_octets += msgb_length(msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llist_empty(&m_queue));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llist_empty(&q->m_queue));</span><br><span> OSMO_ASSERT(llist_empty(&o->m_queue));</span><br><span> </span><br><span> o->m_queue_size = 0;</span><br><span> o->m_queue_octets = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_splice_init(&new_queue, &m_queue);</span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_size = queue_size;</span><br><span style="color: hsl(0, 100%, 40%);">- m_queue_octets = queue_octets;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_splice_init(&new_queue, &q->m_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_size = queue_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ q->m_queue_octets = queue_octets;</span><br><span> }</span><br><span> </span><br><span> #define ALPHA 0.5f</span><br><span>diff --git a/src/llc.h b/src/llc.h</span><br><span>index 3c2e57a..72fa62e 100644</span><br><span>--- a/src/llc.h</span><br><span>+++ b/src/llc.h</span><br><span>@@ -18,9 +18,13 @@</span><br><span> </span><br><span> #pragma once</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> #include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span> #include <stdint.h></span><br><span> #include <string.h></span><br><span>@@ -34,6 +38,8 @@</span><br><span> * I represent the LLC data to a MS</span><br><span> */</span><br><span> struct gprs_llc {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> static bool is_user_data_frame(uint8_t *data, size_t len);</span><br><span> </span><br><span> void init();</span><br><span>@@ -43,92 +49,86 @@</span><br><span> void put_frame(const uint8_t *data, size_t len);</span><br><span> void put_dummy_frame(size_t req_len);</span><br><span> void append_frame(const uint8_t *data, size_t len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- void consume(size_t len);</span><br><span style="color: hsl(0, 100%, 40%);">- void consume(uint8_t *data, size_t len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t chunk_size() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t remaining_space() const;</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t frame_length() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bool fits_in_current_frame(uint8_t size) const;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span> uint8_t frame[LLC_MAX_LEN]; /* current DL or UL frame */</span><br><span> uint16_t m_index; /* current write/read position of frame */</span><br><span> uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct MetaInfo {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timespec recv_time;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timespec expire_time;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span> /**</span><br><span> * I store the LLC frames that come from the SGSN.</span><br><span> */</span><br><span> struct gprs_llc_queue {</span><br><span style="color: hsl(0, 100%, 40%);">- struct MetaInfo {</span><br><span style="color: hsl(0, 100%, 40%);">- struct timespec recv_time;</span><br><span style="color: hsl(0, 100%, 40%);">- struct timespec expire_time;</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> static void calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec,</span><br><span> struct timespec *tv);</span><br><span> static bool is_frame_expired(const struct timespec *now,</span><br><span> const struct timespec *tv);</span><br><span> static bool is_user_data_frame(uint8_t *data, size_t len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void init();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> void enqueue(struct msgb *llc_msg, const struct timespec *expire_time);</span><br><span> struct msgb *dequeue(const MetaInfo **info = 0);</span><br><span style="color: hsl(0, 100%, 40%);">- void clear(BTS *bts);</span><br><span style="color: hsl(0, 100%, 40%);">- void move_and_merge(gprs_llc_queue *o);</span><br><span style="color: hsl(0, 100%, 40%);">- size_t size() const;</span><br><span style="color: hsl(0, 100%, 40%);">- size_t octets() const;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-private:</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> uint32_t m_avg_queue_delay; /* Average delay of data going through the queue */</span><br><span> size_t m_queue_size;</span><br><span> size_t m_queue_octets;</span><br><span> struct llist_head m_queue; /* queued LLC DL data */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_init(struct gprs_llc_queue *q);</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_clear(struct gprs_llc_queue *q, struct BTS *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint16_t gprs_llc::chunk_size() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint16_t llc_chunk_size(const struct gprs_llc *llc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_length - m_index;</span><br><span style="color: hsl(120, 100%, 40%);">+ return llc->m_length - llc->m_index;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint16_t gprs_llc::remaining_space() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint16_t llc_remaining_space(const struct gprs_llc *llc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return LLC_MAX_LEN - m_length;</span><br><span style="color: hsl(120, 100%, 40%);">+ return LLC_MAX_LEN - llc->m_length;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint16_t gprs_llc::frame_length() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint16_t llc_frame_length(const struct gprs_llc *llc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_length;</span><br><span style="color: hsl(120, 100%, 40%);">+ return llc->m_length;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline void gprs_llc::consume(size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void llc_consume(struct gprs_llc *llc, size_t len)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- m_index += len;</span><br><span style="color: hsl(120, 100%, 40%);">+ llc->m_index += len;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline void gprs_llc::consume(uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void llc_consume_data(struct gprs_llc *llc, uint8_t *data, size_t len)</span><br><span> {</span><br><span> /* copy and increment index */</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(data, frame + m_index, len);</span><br><span style="color: hsl(0, 100%, 40%);">- consume(len);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(data, llc->frame + llc->m_index, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume(llc, len);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline bool gprs_llc::fits_in_current_frame(uint8_t chunk_size) const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool llc_fits_in_current_frame(const struct gprs_llc *llc, uint8_t chunk_size)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_length + chunk_size <= LLC_MAX_LEN;</span><br><span style="color: hsl(120, 100%, 40%);">+ return llc->m_length + chunk_size <= LLC_MAX_LEN;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline size_t gprs_llc_queue::size() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline size_t llc_queue_size(const struct gprs_llc_queue *q)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_queue_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ return q->m_queue_size;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline size_t gprs_llc_queue::octets() const</span><br><span style="color: hsl(120, 100%, 40%);">+static inline size_t llc_queue_octets(const struct gprs_llc_queue *q)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_queue_octets;</span><br><span style="color: hsl(120, 100%, 40%);">+ return q->m_queue_octets;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp</span><br><span>index a984591..9cc6270 100644</span><br><span>--- a/src/pcu_l1_if.cpp</span><br><span>+++ b/src/pcu_l1_if.cpp</span><br><span>@@ -318,7 +318,7 @@</span><br><span> struct gprs_rlcmac_bts *bts = bts_main_data();</span><br><span> int rc;</span><br><span> int current_fn = get_current_fn();</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct pcu_l1_meas meas = {0};</span><br><span> uint8_t gsmtap_chantype;</span><br><span> </span><br><span> LOGP(DL1IF, LOGL_DEBUG, "Data indication received: sapi=%d arfcn=%d "</span><br><span>@@ -328,11 +328,11 @@</span><br><span> </span><br><span> switch (data_ind->sapi) {</span><br><span> case PCU_IF_SAPI_PDTCH:</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_rssi(data_ind->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_rssi(&meas, data_ind->rssi);</span><br><span> /* convert BER to % value */</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_ber(data_ind->ber10k / 100);</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_bto(data_ind->ta_offs_qbits);</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_link_qual(data_ind->lqual_cb / 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ber(&meas, data_ind->ber10k / 100);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_bto(&meas, data_ind->ta_offs_qbits);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_link_qual(&meas, data_ind->lqual_cb / 10);</span><br><span> </span><br><span> LOGP(DL1IF, LOGL_DEBUG, "Data indication with raw measurements received: BER10k = %d, BTO = %d, Q = %d\n",</span><br><span> data_ind->ber10k, data_ind->ta_offs_qbits, data_ind->lqual_cb);</span><br><span>@@ -824,8 +824,8 @@</span><br><span> if ((ms = bts->ms_store().get_ms(susp_req->tlli))) {</span><br><span> /* We need to catch both pointers here since MS may become freed</span><br><span> after first tbf_free(dl_tbf) if only DL TBF was available */</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms->dl_tbf();</span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf = ms->ul_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_tbf = ms_ul_tbf(ms);</span><br><span> if (dl_tbf)</span><br><span> tbf_free(dl_tbf);</span><br><span> if (ul_tbf)</span><br><span>@@ -840,7 +840,7 @@</span><br><span> </span><br><span> static int pcu_rx_app_info_req(struct gsm_pcu_if_app_info_req *app_info_req)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> *ms_iter;</span><br><span style="color: hsl(120, 100%, 40%);">+ GprsMs *ms;</span><br><span> BTS *bts = BTS::main_bts();</span><br><span> struct gprs_rlcmac_bts *bts_data = bts->bts_data();</span><br><span> </span><br><span>@@ -848,9 +848,8 @@</span><br><span> app_info_req->application_type, app_info_req->len);</span><br><span> </span><br><span> bts_data->app_info_pending = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each(ms_iter, &bts->ms_store().ms_list()) {</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs *ms = ms_iter->entry();</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms->dl_tbf())</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(ms, bts->ms_store().ms_list(), list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_dl_tbf(ms))</span><br><span> continue;</span><br><span> bts_data->app_info_pending++;</span><br><span> ms->app_info_pending = true;</span><br><span>diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h</span><br><span>index f86e708..65fea9c 100644</span><br><span>--- a/src/pcu_l1_if.h</span><br><span>+++ b/src/pcu_l1_if.h</span><br><span>@@ -79,19 +79,13 @@</span><br><span> unsigned have_ms_i_level:1;</span><br><span> </span><br><span> int16_t ms_i_level; /* I_LEVEL in dB */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas_ts& set_ms_i_level(int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms_i_level = v; have_ms_i_level = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas_ts() :</span><br><span style="color: hsl(0, 100%, 40%);">- have_ms_i_level(0),</span><br><span style="color: hsl(0, 100%, 40%);">- ms_i_level(0)</span><br><span style="color: hsl(0, 100%, 40%);">- {}</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_ts_set_ms_i_level(struct pcu_l1_meas_ts* ts, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ts->ms_i_level = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ ts->have_ms_i_level = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct pcu_l1_meas {</span><br><span> unsigned have_rssi:1;</span><br><span> unsigned have_ber:1;</span><br><span>@@ -111,48 +105,43 @@</span><br><span> int16_t ms_sign_var; /* SIGN_VAR in dB */</span><br><span> </span><br><span> struct pcu_l1_meas_ts ts[8];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_rssi(int8_t v) { rssi = v; have_rssi = 1; return *this;}</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_ber(uint8_t v) { ber = v; have_ber = 1; return *this;}</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_bto(int16_t v) { bto = v; have_bto = 1; return *this;}</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_link_qual(int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- link_qual = v; have_link_qual = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_ms_rx_qual(int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms_rx_qual = v; have_ms_rx_qual = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_ms_c_value(int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms_c_value = v; have_ms_c_value = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_ms_sign_var(int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms_sign_var = v; have_ms_sign_var = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas& set_ms_i_level(size_t idx, int16_t v) {</span><br><span style="color: hsl(0, 100%, 40%);">- ts[idx].set_ms_i_level(v); have_ms_i_level = 1; return *this;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pcu_l1_meas() :</span><br><span style="color: hsl(0, 100%, 40%);">- have_rssi(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_ber(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_bto(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_link_qual(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_ms_rx_qual(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_ms_c_value(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_ms_sign_var(0),</span><br><span style="color: hsl(0, 100%, 40%);">- have_ms_i_level(0),</span><br><span style="color: hsl(0, 100%, 40%);">- rssi(0),</span><br><span style="color: hsl(0, 100%, 40%);">- ber(0),</span><br><span style="color: hsl(0, 100%, 40%);">- bto(0),</span><br><span style="color: hsl(0, 100%, 40%);">- link_qual(0),</span><br><span style="color: hsl(0, 100%, 40%);">- ms_rx_qual(0),</span><br><span style="color: hsl(0, 100%, 40%);">- ms_c_value(0),</span><br><span style="color: hsl(0, 100%, 40%);">- ms_sign_var(0)</span><br><span style="color: hsl(0, 100%, 40%);">- {}</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_rssi(struct pcu_l1_meas *m, int8_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->rssi = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_rssi = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_ber(struct pcu_l1_meas *m, uint8_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->ber = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_ber = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_bto(struct pcu_l1_meas *m, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->bto = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_bto = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_link_qual(struct pcu_l1_meas *m, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->link_qual = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_link_qual = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_ms_rx_qual(struct pcu_l1_meas *m, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->ms_rx_qual = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_ms_rx_qual = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_ms_c_value(struct pcu_l1_meas *m, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->ms_c_value = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_ms_c_value = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_ms_sign_var(struct pcu_l1_meas *m, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ m->ms_sign_var = v;</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_ms_sign_var = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void pcu_l1_meas_set_ms_i_level(struct pcu_l1_meas *m, size_t idx, int16_t v) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_ts_set_ms_i_level(&m->ts[idx], v);</span><br><span style="color: hsl(120, 100%, 40%);">+ m->have_ms_i_level = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">-void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, </span><br><span style="color: hsl(120, 100%, 40%);">+void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,</span><br><span> uint32_t fn, uint8_t block_nr);</span><br><span> void pcu_l1if_tx_ptcch(uint8_t trx, uint8_t ts, uint16_t arfcn,</span><br><span> uint32_t fn, uint8_t block_nr,</span><br><span>diff --git a/src/pcu_utils.h b/src/pcu_utils.h</span><br><span>index 8196a93..cb2fd91 100644</span><br><span>--- a/src/pcu_utils.h</span><br><span>+++ b/src/pcu_utils.h</span><br><span>@@ -15,26 +15,32 @@</span><br><span> * along with this program; if not, write to the Free Software</span><br><span> * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> #include <osmocom/gsm/gsm_utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include <time.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline int msecs_to_frames(int msecs) {</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int msecs_to_frames(int msecs) {</span><br><span> return (msecs * (1024 * 1000 / 4615)) / 1024;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint32_t next_fn(uint32_t fn, uint32_t offset)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint32_t next_fn(uint32_t fn, uint32_t offset)</span><br><span> {</span><br><span> return (fn + offset) % GSM_MAX_FN;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline void csecs_to_timespec(unsigned csecs, struct timespec *ts) {</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void csecs_to_timespec(unsigned csecs, struct timespec *ts) {</span><br><span> ts->tv_sec = csecs / 100;</span><br><span> ts->tv_nsec = (csecs % 100) * 10000000;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> template <typename T></span><br><span> inline unsigned int pcu_bitcount(T x)</span><br><span> {</span><br><span>@@ -44,8 +50,15 @@</span><br><span> </span><br><span> return count;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline uint8_t pcu_lsb(uint8_t x)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t pcu_lsb(uint8_t x)</span><br><span> {</span><br><span> return x & -x;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Used to store a C++ class in a llist used by C code */</span><br><span style="color: hsl(120, 100%, 40%);">+struct llist_item {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list; /* item used by llist */</span><br><span style="color: hsl(120, 100%, 40%);">+ void *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span>diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp</span><br><span>index 416c006..6100b13 100644</span><br><span>--- a/src/pcu_vty_functions.cpp</span><br><span>+++ b/src/pcu_vty_functions.cpp</span><br><span>@@ -61,7 +61,7 @@</span><br><span> tbf->first_ts,</span><br><span> tbf->first_common_ts, tbf->control_ts,</span><br><span> tbf->ms_class(),</span><br><span style="color: hsl(0, 100%, 40%);">- tbf->ms() ? tbf->ms()->egprs_ms_class() : -1,</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf->ms() ? ms_egprs_ms_class(tbf->ms()) : -1,</span><br><span> VTY_NEWLINE);</span><br><span> vty_out(vty, " TS_alloc=");</span><br><span> for (int i = 0; i < 8; i++) {</span><br><span>@@ -79,7 +79,7 @@</span><br><span> ul_tbf->window_size(), win->v_q(), win->v_r());</span><br><span> vty_out(vty, "%s", VTY_NEWLINE);</span><br><span> vty_out(vty, " TBF Statistics:%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (GPRS == tbf->ms()->mode()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (GPRS == ms_mode(tbf->ms())) {</span><br><span> vty_out_rate_ctr_group(vty, " ", ul_tbf->m_ul_gprs_ctrs);</span><br><span> } else {</span><br><span> vty_out_rate_ctr_group(vty, " ", ul_tbf->m_ul_egprs_ctrs);</span><br><span>@@ -92,7 +92,7 @@</span><br><span> win->window_stalled() ? " STALLED" : "");</span><br><span> vty_out(vty, "%s", VTY_NEWLINE);</span><br><span> vty_out_rate_ctr_group(vty, " ", tbf->m_ctrs);</span><br><span style="color: hsl(0, 100%, 40%);">- if (GPRS == tbf->ms()->mode()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (GPRS == ms_mode(tbf->ms())) {</span><br><span> vty_out_rate_ctr_group(vty, " ", dl_tbf->m_dl_gprs_ctrs);</span><br><span> } else {</span><br><span> vty_out_rate_ctr_group(vty, " ", dl_tbf->m_dl_egprs_ctrs);</span><br><span>@@ -124,81 +124,83 @@</span><br><span> static int show_ms(struct vty *vty, GprsMs *ms)</span><br><span> {</span><br><span> unsigned i;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf> *i_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_item *i_tbf;</span><br><span> uint8_t slots;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "MS TLLI=%08x, IMSI=%s%s", ms->tlli(), ms->imsi(), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " Timing advance (TA): %d%s", ms->ta(), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " Coding scheme uplink: %s%s", mcs_name(ms->current_cs_ul()),</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "MS TLLI=%08x, IMSI=%s%s", ms_tlli(ms), ms_imsi(ms), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " Timing advance (TA): %d%s", ms_ta(ms), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " Coding scheme uplink: %s%s", mcs_name(ms_current_cs_ul(ms)),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " Coding scheme downlink: %s%s", mcs_name(ms->current_cs_dl()),</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " Coding scheme downlink: %s%s", mcs_name(ms_current_cs_dl(ms)),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " Mode: %s%s", mode_name(ms->mode()), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " MS class: %d%s", ms->ms_class(), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " EGPRS MS class: %d%s", ms->egprs_ms_class(), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " Mode: %s%s", mode_name(ms_mode(ms)), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " MS class: %d%s", ms_ms_class(ms), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " EGPRS MS class: %d%s", ms_egprs_ms_class(ms), VTY_NEWLINE);</span><br><span> vty_out(vty, " PACCH: ");</span><br><span style="color: hsl(0, 100%, 40%);">- slots = ms->current_pacch_slots();</span><br><span style="color: hsl(120, 100%, 40%);">+ slots = ms_current_pacch_slots(ms);</span><br><span> for (int i = 0; i < 8; i++)</span><br><span> if (slots & (1 << i))</span><br><span> vty_out(vty, "%d ", i);</span><br><span> vty_out(vty, "%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " LLC queue length: %zd%s", ms->llc_queue()->size(),</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " LLC queue length: %zd%s", llc_queue_size(ms_llc_queue(ms)),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " LLC queue octets: %zd%s", ms->llc_queue()->octets(),</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " LLC queue octets: %zd%s", llc_queue_octets(ms_llc_queue(ms)),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_rssi)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_rssi)</span><br><span> vty_out(vty, " RSSI: %d dBm%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->rssi, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_ber)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.rssi, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_ber)</span><br><span> vty_out(vty, " Bit error rate: %d %%%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->ber, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_link_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.ber, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_link_qual)</span><br><span> vty_out(vty, " Link quality: %d dB%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->link_qual, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_bto)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.link_qual, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_bto)</span><br><span> vty_out(vty, " Burst timing offset: %d/4 bit%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->bto, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_ms_rx_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.bto, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_ms_rx_qual)</span><br><span> vty_out(vty, " Downlink NACK rate: %d %%%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->nack_rate_dl(), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_ms_rx_qual)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_nack_rate_dl(ms), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_ms_rx_qual)</span><br><span> vty_out(vty, " MS RX quality: %d %%%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->ms_rx_qual, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_ms_c_value)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.ms_rx_qual, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_ms_c_value)</span><br><span> vty_out(vty, " MS C value: %d dB%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->ms_c_value, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->have_ms_sign_var)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.ms_c_value, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.have_ms_sign_var)</span><br><span> vty_out(vty, " MS SIGN variance: %d dB%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->l1_meas()->ms_sign_var, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < ARRAY_SIZE(ms->l1_meas()->ts); ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->l1_meas()->ts[i].have_ms_i_level)</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->l1_meas.ms_sign_var, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_SIZE(ms->l1_meas.ts); ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms->l1_meas.ts[i].have_ms_i_level)</span><br><span> vty_out(vty, " MS I level (slot %d): %d dB%s",</span><br><span style="color: hsl(0, 100%, 40%);">- i, ms->l1_meas()->ts[i].ms_i_level, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ i, ms->l1_meas.ts[i].ms_i_level, VTY_NEWLINE);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " RLC/MAC DL Control Msg: %d%s", ms->dl_ctrl_msg(),</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " RLC/MAC DL Control Msg: %d%s", ms_dl_ctrl_msg(ms),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->ul_tbf())</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_ul_tbf(ms))</span><br><span> vty_out(vty, " Uplink TBF: TFI=%d, state=%s%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ul_tbf()->tfi(),</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ul_tbf()->state_name(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ul_tbf(ms)->tfi(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ul_tbf(ms)->state_name(),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->dl_tbf()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_dl_tbf(ms)) {</span><br><span> vty_out(vty, " Downlink TBF: TFI=%d, state=%s%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf()->tfi(),</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf()->state_name(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms)->tfi(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms)->state_name(),</span><br><span> VTY_NEWLINE);</span><br><span> vty_out(vty, " Current DL Throughput: %d Kbps %s",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf()->m_bw.dl_throughput,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms)->m_bw.dl_throughput,</span><br><span> VTY_NEWLINE);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each(i_tbf, &ms->old_tbfs())</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(i_tbf, &ms->old_tbfs, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)i_tbf->entry;</span><br><span> vty_out(vty, " Old %-19s TFI=%d, state=%s%s",</span><br><span style="color: hsl(0, 100%, 40%);">- i_tbf->entry()->direction == GPRS_RLCMAC_UL_TBF ?</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_direction(tbf) == GPRS_RLCMAC_UL_TBF ?</span><br><span> "Uplink TBF:" : "Downlink TBF:",</span><br><span style="color: hsl(0, 100%, 40%);">- i_tbf->entry()->tfi(),</span><br><span style="color: hsl(0, 100%, 40%);">- i_tbf->entry()->state_name(),</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf->tfi(),</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf->state_name(),</span><br><span> VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> return CMD_SUCCESS;</span><br><span> }</span><br><span>@@ -206,10 +208,10 @@</span><br><span> int pcu_vty_show_ms_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data)</span><br><span> {</span><br><span> BTS *bts = bts_data->bts;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<GprsMs> *ms_iter;</span><br><span style="color: hsl(120, 100%, 40%);">+ GprsMs *ms_iter;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each(ms_iter, &bts->ms_store().ms_list())</span><br><span style="color: hsl(0, 100%, 40%);">- show_ms(vty, ms_iter->entry());</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(ms_iter, bts->ms_store().ms_list(), list)</span><br><span style="color: hsl(120, 100%, 40%);">+ show_ms(vty, ms_iter);</span><br><span> </span><br><span> return CMD_SUCCESS;</span><br><span> }</span><br><span>diff --git a/src/pdch.cpp b/src/pdch.cpp</span><br><span>index 4a0ff06..49cce8d 100644</span><br><span>--- a/src/pdch.cpp</span><br><span>+++ b/src/pdch.cpp</span><br><span>@@ -68,9 +68,9 @@</span><br><span> 18, /* 18,10 % */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_rx_qual(rx_qual_map[</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_MIN(rx_qual_enc, ARRAY_SIZE(rx_qual_map)-1)</span><br><span style="color: hsl(0, 100%, 40%);">- ]);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_rx_qual(meas, rx_qual_map[</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_MIN(rx_qual_enc, ARRAY_SIZE(rx_qual_map)-1)</span><br><span style="color: hsl(120, 100%, 40%);">+ ]);</span><br><span> }</span><br><span> </span><br><span> static void get_meas(struct pcu_l1_meas *meas,</span><br><span>@@ -78,9 +78,9 @@</span><br><span> {</span><br><span> unsigned i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_c_value(qr->C_VALUE);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_c_value(meas, qr->C_VALUE);</span><br><span> if (qr->Exist_SIGN_VAR)</span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_sign_var(meas, (qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */</span><br><span> </span><br><span> for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->I_LEVEL_TN), ARRAY_SIZE(meas->ts)); i++)</span><br><span> {</span><br><span>@@ -88,7 +88,7 @@</span><br><span> LOGP(DRLCMAC, LOGL_INFO,</span><br><span> "Packet resource request: i_level[%d] = %d\n",</span><br><span> i, qr->I_LEVEL_TN[i].I_LEVEL);</span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_i_level(i, -2 * qr->I_LEVEL_TN[i].I_LEVEL);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_i_level(meas, i, -2 * qr->I_LEVEL_TN[i].I_LEVEL);</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span>@@ -99,8 +99,8 @@</span><br><span> unsigned i;</span><br><span> </span><br><span> get_rx_qual_meas(meas, qr->RXQUAL);</span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_c_value(qr->C_VALUE);</span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_c_value(meas, qr->C_VALUE);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_sign_var(meas, (qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */</span><br><span> </span><br><span> for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->Slot), ARRAY_SIZE(meas->ts)); i++)</span><br><span> {</span><br><span>@@ -108,7 +108,7 @@</span><br><span> LOGP(DRLCMAC, LOGL_DEBUG,</span><br><span> "Channel quality report: i_level[%d] = %d\n",</span><br><span> i, qr->Slot[i].I_LEVEL_TN);</span><br><span style="color: hsl(0, 100%, 40%);">- meas->set_ms_i_level(i, -2 * qr->Slot[i].I_LEVEL_TN);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_ms_i_level(meas, i, -2 * qr->Slot[i].I_LEVEL_TN);</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span>@@ -307,11 +307,11 @@</span><br><span> LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "</span><br><span> "unknown TBF corresponds to MS with IMSI %s, TA %d, "</span><br><span> "uTBF (TFI=%d, state=%s), dTBF (TFI=%d, state=%s)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->imsi(), ms->ta(),</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ul_tbf() ? ms->ul_tbf()->tfi() : 0,</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ul_tbf() ? ms->ul_tbf()->state_name() : "None",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf() ? ms->dl_tbf()->tfi() : 0,</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf() ? ms->dl_tbf()->state_name() : "None");</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_imsi(ms), ms_ta(ms),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ul_tbf(ms) ? ms_ul_tbf(ms)->tfi() : 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ul_tbf(ms) ? ms_ul_tbf(ms)->state_name() : "None",</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms) ? ms_dl_tbf(ms)->tfi() : 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms) ? ms_dl_tbf(ms)->state_name() : "None");</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span>@@ -339,7 +339,7 @@</span><br><span> tbf->n_reset(N3105);</span><br><span> TBF_SET_ASS_STATE_DL(tbf, GPRS_RLCMAC_DL_ASS_NONE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- new_tbf = tbf->ms() ? tbf->ms()->dl_tbf() : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ new_tbf = tbf->ms() ? ms_dl_tbf(tbf->ms()) : NULL;</span><br><span> if (!new_tbf) {</span><br><span> LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "</span><br><span> "TBF is gone TLLI=0x%08x\n", tlli);</span><br><span>@@ -371,7 +371,7 @@</span><br><span> tbf->n_reset(N3105);</span><br><span> TBF_SET_ASS_STATE_UL(tbf, GPRS_RLCMAC_UL_ASS_NONE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- new_tbf = tbf->ms() ? tbf->ms()->ul_tbf() : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ new_tbf = tbf->ms() ? ms_ul_tbf(tbf->ms()) : NULL;</span><br><span> if (!new_tbf) {</span><br><span> LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "</span><br><span> "TBF is gone TLLI=0x%08x\n", tlli);</span><br><span>@@ -389,7 +389,7 @@</span><br><span> /* there might be LLC packets waiting in the queue, but the DL</span><br><span> * TBF might have been released while the UL TBF has been</span><br><span> * established */</span><br><span style="color: hsl(0, 100%, 40%);">- if (new_tbf->ms()->need_dl_tbf())</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_need_dl_tbf(new_tbf->ms()))</span><br><span> new_tbf->establish_dl_tbf_on_pacch();</span><br><span> </span><br><span> return;</span><br><span>@@ -460,7 +460,7 @@</span><br><span> /* get measurements */</span><br><span> if (tbf->ms()) {</span><br><span> get_meas(meas, &ack_nack->Channel_Quality_Report);</span><br><span style="color: hsl(0, 100%, 40%);">- tbf->ms()->update_l1_meas(meas);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_l1_meas(tbf->ms(), meas);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -570,19 +570,19 @@</span><br><span> if (!ms) {</span><br><span> ms_found = false;</span><br><span> ms = bts()->ms_alloc(0, 0); /* ms class updated later */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, tlli);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf = ms->ul_tbf(); /* hence ul_tbf may be NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_tbf = ms_ul_tbf(ms); /* hence ul_tbf may be NULL */</span><br><span> </span><br><span> /* Keep the ms, even if it gets idle temporarily */</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span> </span><br><span> LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "</span><br><span> "in packet resource request of single "</span><br><span> "block, so we provide one:\n");</span><br><span> sba = bts()->sba()->find(this, fn);</span><br><span> if (sba) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ta(sba->ta);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ta(ms, sba->ta);</span><br><span> bts()->sba()->free_sba(sba);</span><br><span> } else if (!ul_tbf || !ul_tbf->state_is(GPRS_RLCMAC_FINISHED)) {</span><br><span> LOGPTBFUL(ul_tbf, LOGL_NOTICE,</span><br><span>@@ -599,9 +599,9 @@</span><br><span> ms_class = Decoding::get_ms_class_by_capability(&request->MS_Radio_Access_capability2);</span><br><span> egprs_ms_class = Decoding::get_egprs_ms_class_by_capability(&request->MS_Radio_Access_capability2);</span><br><span> if (ms_class)</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ms_class(ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ms_class(ms, ms_class);</span><br><span> if (egprs_ms_class)</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_egprs_ms_class(egprs_ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_egprs_ms_class(ms, egprs_ms_class);</span><br><span> }</span><br><span> </span><br><span> /* Get rid of previous finished UL TBF before providing a new one */</span><br><span>@@ -616,7 +616,7 @@</span><br><span> if (!ul_tbf) {</span><br><span> handle_tbf_reject(bts_data(), ms, tlli,</span><br><span> trx_no(), ts_no);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(120, 100%, 40%);">+ goto return_unref;</span><br><span> }</span><br><span> </span><br><span> /* set control ts to current MS's TS, until assignment complete */</span><br><span>@@ -630,8 +630,10 @@</span><br><span> /* get measurements */</span><br><span> if (ul_tbf->ms()) {</span><br><span> get_meas(meas, request);</span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf->ms()->update_l1_meas(meas);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_l1_meas(ul_tbf->ms(), meas);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+return_unref:</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span>@@ -674,10 +676,10 @@</span><br><span> LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "</span><br><span> "but TLLI 0x%08x is unknown\n", report->TLLI);</span><br><span> ms = bts()->ms_alloc(0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(report->TLLI);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, report->TLLI);</span><br><span> }</span><br><span> if ((sba = bts()->sba()->find(this, fn))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ta(sba->ta);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ta(ms, sba->ta);</span><br><span> bts()->sba()->free_sba(sba);</span><br><span> }</span><br><span> gprs_rlcmac_meas_rep(ms, report);</span><br><span>diff --git a/src/tbf.cpp b/src/tbf.cpp</span><br><span>index e92dfb6..fde44ba 100644</span><br><span>--- a/src/tbf.cpp</span><br><span>+++ b/src/tbf.cpp</span><br><span>@@ -141,14 +141,13 @@</span><br><span> m_tfi(0),</span><br><span> m_created_ts(0),</span><br><span> m_ctrs(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms(ms),</span><br><span> state(GPRS_RLCMAC_NULL),</span><br><span style="color: hsl(120, 100%, 40%);">+ m_ms(ms),</span><br><span> dl_ass_state(GPRS_RLCMAC_DL_ASS_NONE),</span><br><span> ul_ass_state(GPRS_RLCMAC_UL_ASS_NONE),</span><br><span> ul_ack_state(GPRS_RLCMAC_UL_ACK_NONE),</span><br><span> poll_state(GPRS_RLCMAC_POLL_NONE),</span><br><span> m_list(this),</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms_list(this),</span><br><span> m_egprs_enabled(false)</span><br><span> {</span><br><span> /* The classes of these members do not have proper constructors yet.</span><br><span>@@ -158,6 +157,9 @@</span><br><span> memset(&Narr, 0, sizeof(Narr));</span><br><span> memset(&gsm_timer, 0, sizeof(gsm_timer));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&m_ms_list, 0, sizeof(m_ms_list));</span><br><span style="color: hsl(120, 100%, 40%);">+ m_ms_list.entry = this;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> m_rlc.init();</span><br><span> m_llc.init();</span><br><span> </span><br><span>@@ -171,27 +173,27 @@</span><br><span> </span><br><span> uint32_t gprs_rlcmac_tbf::tlli() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms ? m_ms->tlli() : GSM_RESERVED_TMSI;</span><br><span style="color: hsl(120, 100%, 40%);">+ return m_ms ? ms_tlli(m_ms) : GSM_RESERVED_TMSI;</span><br><span> }</span><br><span> </span><br><span> const char *gprs_rlcmac_tbf::imsi() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms->imsi();</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms_imsi(m_ms);</span><br><span> }</span><br><span> </span><br><span> uint8_t gprs_rlcmac_tbf::ta() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms->ta();</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms_ta(m_ms);</span><br><span> }</span><br><span> </span><br><span> void gprs_rlcmac_tbf::set_ta(uint8_t ta)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->set_ta(ta);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ta(m_ms, ta);</span><br><span> }</span><br><span> </span><br><span> uint8_t gprs_rlcmac_tbf::ms_class() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms->ms_class();</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms_ms_class(m_ms);</span><br><span> }</span><br><span> </span><br><span> enum CodingScheme gprs_rlcmac_tbf::current_cs() const</span><br><span>@@ -199,28 +201,21 @@</span><br><span> enum CodingScheme cs;</span><br><span> </span><br><span> if (direction == GPRS_RLCMAC_UL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- cs = m_ms ? m_ms->current_cs_ul() : UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ cs = m_ms ? ms_current_cs_ul(m_ms) : UNKNOWN;</span><br><span> else</span><br><span style="color: hsl(0, 100%, 40%);">- cs = m_ms ? m_ms->current_cs_dl() : UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ cs = m_ms ? ms_current_cs_dl(m_ms) : UNKNOWN;</span><br><span> </span><br><span> return cs;</span><br><span> }</span><br><span> </span><br><span> gprs_llc_queue *gprs_rlcmac_tbf::llc_queue()</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms ? m_ms->llc_queue() : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ return m_ms ? ms_llc_queue(m_ms) : NULL;</span><br><span> }</span><br><span> </span><br><span> const gprs_llc_queue *gprs_rlcmac_tbf::llc_queue() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms ? m_ms->llc_queue() : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-size_t gprs_rlcmac_tbf::llc_queue_size() const</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- /* m_ms->llc_queue() never returns NULL: GprsMs::m_llc_queue is a</span><br><span style="color: hsl(0, 100%, 40%);">- * member instance. */</span><br><span style="color: hsl(0, 100%, 40%);">- return m_ms ? m_ms->llc_queue()->size() : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ms_llc_queue(m_ms);</span><br><span> }</span><br><span> </span><br><span> void gprs_rlcmac_tbf::set_ms(GprsMs *ms)</span><br><span>@@ -229,13 +224,13 @@</span><br><span> return;</span><br><span> </span><br><span> if (m_ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms->detach_tbf(this);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(m_ms, this);</span><br><span> }</span><br><span> </span><br><span> m_ms = ms;</span><br><span> </span><br><span> if (m_ms)</span><br><span style="color: hsl(0, 100%, 40%);">- m_ms->attach_tbf(this);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(m_ms, this);</span><br><span> }</span><br><span> </span><br><span> void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)</span><br><span>@@ -247,18 +242,18 @@</span><br><span> * MS object that belongs to that TLLI and if yes make sure one of them</span><br><span> * gets deleted. This is the same problem that can arise with</span><br><span> * IMSI in gprs_rlcmac_dl_tbf::handle() so there should be a unified solution */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms()->check_tlli(tlli)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_check_tlli(ms(), tlli)) {</span><br><span> GprsMs *old_ms;</span><br><span> </span><br><span> old_ms = bts->ms_store().get_ms(tlli, 0, NULL);</span><br><span> if (old_ms)</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->merge_and_clear_ms(old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_merge_and_clear_ms(ms(), old_ms);</span><br><span> }</span><br><span> </span><br><span> if (dir == GPRS_RLCMAC_UL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->set_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms(), tlli);</span><br><span> else</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->confirm_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms(), tlli);</span><br><span> }</span><br><span> </span><br><span> static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)</span><br><span>@@ -745,7 +740,7 @@</span><br><span> struct gprs_rlcmac_bts *bts_data = bts->bts_data();</span><br><span> int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (m_ms->mode() != GPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_mode(m_ms) != GPRS)</span><br><span> enable_egprs();</span><br><span> </span><br><span> m_created_ts = time(NULL);</span><br><span>@@ -775,7 +770,7 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- m_ms->attach_tbf(this);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(m_ms, this);</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span>@@ -895,7 +890,7 @@</span><br><span> }</span><br><span> </span><br><span> if (ms())</span><br><span style="color: hsl(0, 100%, 40%);">- new_dl_tbf = ms()->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ new_dl_tbf = ms_dl_tbf(ms());</span><br><span> </span><br><span> if (!new_dl_tbf) {</span><br><span> LOGPTBFDL(this, LOGL_ERROR,</span><br><span>@@ -1012,7 +1007,7 @@</span><br><span> return NULL;</span><br><span> </span><br><span> if (ms())</span><br><span style="color: hsl(0, 100%, 40%);">- new_tbf = ms()->ul_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ new_tbf = ms_ul_tbf(ms());</span><br><span> if (!new_tbf) {</span><br><span> LOGPTBFUL(this, LOGL_ERROR,</span><br><span> "We have a schedule for uplink assignment, but there is no uplink TBF\n");</span><br><span>@@ -1170,3 +1165,58 @@</span><br><span> {</span><br><span> return ts == control_ts;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* C API */</span><br><span style="color: hsl(120, 100%, 40%);">+enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->state;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->direction;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf->set_ms(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return &tbf->m_ms_list.list;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *tbf_ms(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->ms();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->timers_pending(t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return &tbf->m_llc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->first_common_ts;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->dl_slots();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->ul_slots();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf->is_tfi_assigned();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/tbf.h b/src/tbf.h</span><br><span>index c97477b..4bbfea2 100644</span><br><span>--- a/src/tbf.h</span><br><span>+++ b/src/tbf.h</span><br><span>@@ -25,11 +25,21 @@</span><br><span> #include "llc.h"</span><br><span> #include "rlc.h"</span><br><span> #include "cxx_linuxlist.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "pcu_utils.h"</span><br><span> #include <gprs_debug.h></span><br><span> #include <gsm_timer.h></span><br><span> #include <stdint.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct bssgp_bvc_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_bts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> #include <osmocom/core/utils.h></span><br><span> #include <osmocom/core/linuxlist.h></span><br><span> #include <osmocom/core/logging.h></span><br><span>@@ -37,12 +47,8 @@</span><br><span> #include <osmocom/gsm/gsm48.h></span><br><span> </span><br><span> #include "coding_scheme.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct bssgp_bvc_ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-class GprsMs;</span><br><span style="color: hsl(0, 100%, 40%);">-struct gprs_rlcmac_bts;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #endif</span><br><span> </span><br><span> /*</span><br><span>@@ -182,6 +188,28 @@</span><br><span> #define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)</span><br><span> </span><br><span> #ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+const char *tbf_name(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, struct GprsMs *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+struct GprsMs *tbf_ms(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t);</span><br><span style="color: hsl(120, 100%, 40%);">+void tbf_free(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span> </span><br><span> struct gprs_rlcmac_tbf {</span><br><span> gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);</span><br><span>@@ -255,7 +283,6 @@</span><br><span> void set_ta(uint8_t);</span><br><span> uint8_t ms_class() const;</span><br><span> enum CodingScheme current_cs() const;</span><br><span style="color: hsl(0, 100%, 40%);">- size_t llc_queue_size() const;</span><br><span> </span><br><span> time_t created_ts() const;</span><br><span> uint8_t dl_slots() const;</span><br><span>@@ -269,9 +296,6 @@</span><br><span> /* attempt to make things a bit more fair */</span><br><span> void rotate_in_list();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}</span><br><span style="color: hsl(0, 100%, 40%);">- const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> LListHead<gprs_rlcmac_tbf>& list();</span><br><span> const LListHead<gprs_rlcmac_tbf>& list() const;</span><br><span> </span><br><span>@@ -321,6 +345,8 @@</span><br><span> time_t m_created_ts;</span><br><span> </span><br><span> struct rate_ctr_group *m_ctrs;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum gprs_rlcmac_tbf_state state;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_item m_ms_list;</span><br><span> </span><br><span> protected:</span><br><span> gprs_rlcmac_bts *bts_data() const;</span><br><span>@@ -331,26 +357,20 @@</span><br><span> </span><br><span> static const char *tbf_state_name[6];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- class GprsMs *m_ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *m_ms;</span><br><span> private:</span><br><span> void enable_egprs();</span><br><span style="color: hsl(0, 100%, 40%);">- enum gprs_rlcmac_tbf_state state;</span><br><span> enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;</span><br><span> enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;</span><br><span> enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;</span><br><span> enum gprs_rlcmac_tbf_poll_state poll_state;</span><br><span> LListHead<gprs_rlcmac_tbf> m_list;</span><br><span style="color: hsl(0, 100%, 40%);">- LListHead<gprs_rlcmac_tbf> m_ms_list;</span><br><span> bool m_egprs_enabled;</span><br><span> struct osmo_timer_list Tarr[T_MAX];</span><br><span> uint8_t Narr[N_MAX];</span><br><span> mutable char m_name_buf[60];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void tbf_free(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const</span><br><span> {</span><br><span> return state == rhs;</span><br><span>@@ -381,8 +401,6 @@</span><br><span> return state != rhs;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-const char *tbf_name(gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> inline const char *gprs_rlcmac_tbf::state_name() const</span><br><span> {</span><br><span> return tbf_state_name[state];</span><br><span>diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp</span><br><span>index bb89e81..613f7b8 100644</span><br><span>--- a/src/tbf_dl.cpp</span><br><span>+++ b/src/tbf_dl.cpp</span><br><span>@@ -131,7 +131,7 @@</span><br><span> </span><br><span> LOGP(DTBF, LOGL_DEBUG, "********** DL-TBF starts here **********\n");</span><br><span> LOGP(DTBF, LOGL_INFO, "Allocating DL TBF: MS_CLASS=%d/%d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ms_class(), ms->egprs_ms_class());</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ms_class(ms), ms_egprs_ms_class(ms));</span><br><span> </span><br><span> tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> </span><br><span>@@ -241,7 +241,7 @@</span><br><span> struct gprs_rlcmac_ul_tbf *ul_tbf = NULL, *old_ul_tbf;</span><br><span> struct gprs_rlcmac_dl_tbf *dl_tbf = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf = ms->ul_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_tbf = ms_ul_tbf(ms);</span><br><span> </span><br><span> if (ul_tbf && ul_tbf->m_contention_resolution_done</span><br><span> && !ul_tbf->m_final_ack_sent) {</span><br><span>@@ -291,41 +291,43 @@</span><br><span> /* check for existing TBF */</span><br><span> ms = bts->bts->ms_store().get_ms(tlli, tlli_old, imsi);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ms && strlen(ms->imsi()) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms && strlen(ms_imsi(ms)) == 0) {</span><br><span> ms_old = bts->bts->ms_store().get_ms(0, 0, imsi);</span><br><span> if (ms_old && ms_old != ms) {</span><br><span> /* The TLLI has changed (RAU), so there are two MS</span><br><span> * objects for the same MS */</span><br><span> LOGP(DTBF, LOGL_NOTICE,</span><br><span> "There is a new MS object for the same MS: (0x%08x, '%s') -> (0x%08x, '%s')\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ms_old->tlli(), ms_old->imsi(), ms->tlli(), ms->imsi());</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_tlli(ms_old), ms_imsi(ms_old), ms_tlli(ms), ms_imsi(ms));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard_old(ms_old);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms_old);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms->dl_tbf() && ms_old->dl_tbf()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_dl_tbf(ms) && ms_dl_tbf(ms_old)) {</span><br><span> LOGP(DTBF, LOGL_NOTICE,</span><br><span> "IMSI %s, old TBF %s: moving DL TBF to new MS object\n",</span><br><span style="color: hsl(0, 100%, 40%);">- imsi, ms_old->dl_tbf()->name());</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms_old->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ imsi, ms_dl_tbf(ms_old)->name());</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms_old);</span><br><span> /* Move the DL TBF to the new MS */</span><br><span> dl_tbf->set_ms(ms);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- ms->merge_and_clear_ms(ms_old);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_merge_and_clear_ms(ms, ms_old);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms_old);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span> if (!ms)</span><br><span> ms = bts->bts->ms_alloc(ms_class, egprs_ms_class);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_imsi(imsi);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms->ms_class() && ms_class) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ms_class(ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(ms, imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_ms_class(ms) && ms_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ms_class(ms, ms_class);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms->egprs_ms_class() && egprs_ms_class) {</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_egprs_ms_class(egprs_ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ms_egprs_ms_class(ms) && egprs_ms_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_egprs_ms_class(ms, egprs_ms_class);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms);</span><br><span> if (!dl_tbf) {</span><br><span> rc = tbf_new_dl_assignment(bts, ms, &dl_tbf);</span><br><span> if (rc < 0)</span><br><span>@@ -344,7 +346,7 @@</span><br><span> uint32_t octets = 0, frames = 0;</span><br><span> struct timespec hyst_delta = {0, 0};</span><br><span> const unsigned keep_small_thresh = 60;</span><br><span style="color: hsl(0, 100%, 40%);">- const gprs_llc_queue::MetaInfo *info;</span><br><span style="color: hsl(120, 100%, 40%);">+ const MetaInfo *info;</span><br><span> </span><br><span> if (bts_data()->llc_discard_csec)</span><br><span> csecs_to_timespec(bts_data()->llc_discard_csec, &hyst_delta);</span><br><span>@@ -358,9 +360,9 @@</span><br><span> </span><br><span> gprs_bssgp_update_queue_delay(tv_recv, &tv_now);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ms() && ms()->codel_state()) {</span><br><span style="color: hsl(0, 100%, 40%);">- int bytes = llc_queue()->octets();</span><br><span style="color: hsl(0, 100%, 40%);">- if (gprs_codel_control(ms()->codel_state(),</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms() && ms_codel_state(ms())) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int bytes = llc_queue_octets(llc_queue());</span><br><span style="color: hsl(120, 100%, 40%);">+ if (gprs_codel_control(ms_codel_state(ms()),</span><br><span> tv_recv, &tv_now, bytes))</span><br><span> goto drop_frame;</span><br><span> }</span><br><span>@@ -402,7 +404,7 @@</span><br><span> LOGPTBFDL(this, LOGL_NOTICE, "Discarding LLC PDU "</span><br><span> "because lifetime limit reached, "</span><br><span> "count=%u new_queue_size=%zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">- frames, llc_queue_size());</span><br><span style="color: hsl(120, 100%, 40%);">+ frames, llc_queue_size(llc_queue()));</span><br><span> if (frames > 0xff)</span><br><span> frames = 0xff;</span><br><span> if (octets > 0xffffff)</span><br><span>@@ -459,7 +461,7 @@</span><br><span> } else if (bsn < 0 && is_egprs_enabled() && req_mcs_kind == EGPRS_GMSK) {</span><br><span> /* New data to be sent for EGPRS TBF but we are required to downgrade to</span><br><span> * MCS1-4, because USF for GPRS-only MS will be sent */</span><br><span style="color: hsl(0, 100%, 40%);">- force_cs = m_ms->current_cs_dl();</span><br><span style="color: hsl(120, 100%, 40%);">+ force_cs = ms_current_cs_dl(m_ms);</span><br><span> if (force_cs > MCS4) {</span><br><span> force_cs = bts->cs_dl_is_supported(MCS4) ? MCS4 :</span><br><span> bts->cs_dl_is_supported(MCS3) ? MCS3 :</span><br><span>@@ -467,7 +469,7 @@</span><br><span> MCS1;</span><br><span> LOGPTBFDL(this, LOGL_DEBUG,</span><br><span> "Force downgrading DL %s -> %s due to USF for GPRS-only MS\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(m_ms->current_cs_dl()), mcs_name(force_cs));</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms_current_cs_dl(m_ms)), mcs_name(force_cs));</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -483,14 +485,14 @@</span><br><span> if (is_egprs_enabled()) {</span><br><span> /* Table 8.1.1.2 and Table 8.1.1.1 of 44.060 */</span><br><span> m_rlc.block(bsn)->cs_current_trans = get_retx_mcs(m_rlc.block(bsn)->cs_init,</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->current_cs_dl(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_current_cs_dl(ms()),</span><br><span> !bts->bts_data()->dl_arq_type);</span><br><span> </span><br><span> LOGPTBFDL(this, LOGL_DEBUG,</span><br><span> "initial_cs_dl(%s) last_mcs(%s) demanded_mcs(%s) cs_trans(%s) arq_type(%d) bsn(%d)\n",</span><br><span> mcs_name(m_rlc.block(bsn)->cs_init),</span><br><span> mcs_name(m_rlc.block(bsn)->cs_last),</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(ms()->current_cs_dl()),</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms_current_cs_dl(ms())),</span><br><span> mcs_name(m_rlc.block(bsn)->cs_current_trans),</span><br><span> bts->bts_data()->dl_arq_type, bsn);</span><br><span> </span><br><span>@@ -635,7 +637,7 @@</span><br><span> {</span><br><span> struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (m_llc.frame_length() != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (llc_frame_length(&m_llc) != 0)</span><br><span> return;</span><br><span> </span><br><span> /* dequeue next LLC frame, if any */</span><br><span>@@ -661,7 +663,7 @@</span><br><span> int write_offset = 0;</span><br><span> Encoding::AppendResult ar;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (m_llc.frame_length() == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (llc_frame_length(&m_llc) == 0)</span><br><span> schedule_next_frame();</span><br><span> </span><br><span> OSMO_ASSERT(mcs_is_valid(cs));</span><br><span>@@ -693,7 +695,7 @@</span><br><span> bool is_final;</span><br><span> int payload_written = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (m_llc.frame_length() == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (llc_frame_length(&m_llc) == 0) {</span><br><span> /* It is not clear, when the next real data will</span><br><span> * arrive, so request a DL ack/nack now */</span><br><span> request_dl_ack();</span><br><span>@@ -731,10 +733,10 @@</span><br><span> </span><br><span> LOGPTBFDL(this, LOGL_DEBUG,</span><br><span> "Empty chunk, added LLC dummy command of size %d, drained_since=%d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- m_llc.frame_length(), frames_since_last_drain(fn));</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_frame_length(&m_llc), frames_since_last_drain(fn));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- is_final = llc_queue_size() == 0 && !keep_open(fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ is_final = llc_queue_size(llc_queue()) == 0 && !keep_open(fn);</span><br><span> </span><br><span> ar = Encoding::rlc_data_to_dl_append(rdbi, cs,</span><br><span> &m_llc, &write_offset, &num_chunks, data, is_final, &payload_written);</span><br><span>@@ -745,9 +747,9 @@</span><br><span> if (ar == Encoding::AR_NEED_MORE_BLOCKS)</span><br><span> break;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- LOGPTBFDL(this, LOGL_DEBUG, "Complete DL frame, len=%d\n", m_llc.frame_length());</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_rlcmac_dl_bw(this, m_llc.frame_length());</span><br><span style="color: hsl(0, 100%, 40%);">- bts->do_rate_ctr_add(CTR_LLC_DL_BYTES, m_llc.frame_length());</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPTBFDL(this, LOGL_DEBUG, "Complete DL frame, len=%d\n", llc_frame_length(&m_llc));</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_rlcmac_dl_bw(this, llc_frame_length(&m_llc));</span><br><span style="color: hsl(120, 100%, 40%);">+ bts->do_rate_ctr_add(CTR_LLC_DL_BYTES, llc_frame_length(&m_llc));</span><br><span> m_llc.reset();</span><br><span> </span><br><span> if (is_final) {</span><br><span>@@ -1131,7 +1133,7 @@</span><br><span> error_rate = analyse_errors(show_rbb, behind_last_bsn, &ana_res);</span><br><span> </span><br><span> if (bts_data()->cs_adj_enabled && ms())</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->update_error_rate(this, error_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_error_rate(ms(), this, error_rate);</span><br><span> </span><br><span> m_window.update(bts, rbb, first_bsn, &lost, &received);</span><br><span> rate_ctr_add(&m_ctrs->ctr[TBF_CTR_RLC_NACKED], lost);</span><br><span>@@ -1186,7 +1188,7 @@</span><br><span> error_rate = analyse_errors(show_rbb, ssn, &ana_res);</span><br><span> </span><br><span> if (bts_data()->cs_adj_enabled && ms())</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->update_error_rate(this, error_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_error_rate(ms(), this, error_rate);</span><br><span> </span><br><span> m_window.update(bts, show_rbb, ssn,</span><br><span> &lost, &received);</span><br><span>@@ -1221,7 +1223,7 @@</span><br><span> release();</span><br><span> </span><br><span> /* check for LLC PDU in the LLC Queue */</span><br><span style="color: hsl(0, 100%, 40%);">- if (llc_queue_size() > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (llc_queue_size(llc_queue()) > 0)</span><br><span> /* we have more data so we will re-use this tbf */</span><br><span> establish_dl_tbf_on_pacch();</span><br><span> </span><br><span>@@ -1331,8 +1333,8 @@</span><br><span> </span><br><span> bool gprs_rlcmac_dl_tbf::have_data() const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return m_llc.chunk_size() > 0 ||</span><br><span style="color: hsl(0, 100%, 40%);">- (llc_queue_size() > 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ return llc_chunk_size(&m_llc) > 0 ||</span><br><span style="color: hsl(120, 100%, 40%);">+ (llc_queue_size(llc_queue()) > 0);</span><br><span> }</span><br><span> </span><br><span> static inline int frames_since_last(int32_t last, unsigned fn)</span><br><span>@@ -1556,3 +1558,11 @@</span><br><span> mcs_name(cs));</span><br><span> }</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_dl_tbf *as_dl_tbf(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)</span><br><span style="color: hsl(120, 100%, 40%);">+ return static_cast<gprs_rlcmac_dl_tbf *>(tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/tbf_dl.h b/src/tbf_dl.h</span><br><span>index ffb370c..3cd88c9 100644</span><br><span>--- a/src/tbf_dl.h</span><br><span>+++ b/src/tbf_dl.h</span><br><span>@@ -141,15 +141,17 @@</span><br><span> return m_window.ws();</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- return static_cast<gprs_rlcmac_dl_tbf *>(tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms,</span><br><span> int8_t use_trx, bool single_slot);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#else /* ifdef __cplusplus */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_dl_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_dl_tbf *as_dl_tbf(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> #endif</span><br><span>diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp</span><br><span>index 80a8eaa..f8c860c 100644</span><br><span>--- a/src/tbf_ul.cpp</span><br><span>+++ b/src/tbf_ul.cpp</span><br><span>@@ -105,7 +105,7 @@</span><br><span> </span><br><span> LOGP(DTBF, LOGL_DEBUG, "********** UL-TBF starts here **********\n");</span><br><span> LOGP(DTBF, LOGL_INFO, "Allocating UL TBF: MS_CLASS=%d/%d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ms->ms_class(), ms->egprs_ms_class());</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ms_class(ms), ms_egprs_ms_class(ms));</span><br><span> </span><br><span> tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> if (!tbf)</span><br><span>@@ -172,7 +172,7 @@</span><br><span> </span><br><span> if (!ms)</span><br><span> ms = bts->bts->ms_alloc(0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, tlli);</span><br><span> </span><br><span> ul_tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> if (!ul_tbf)</span><br><span>@@ -185,7 +185,7 @@</span><br><span> ul_tbf->bts->do_rate_ctr_inc(CTR_TBF_UL_ALLOCATED);</span><br><span> TBF_SET_ASS_ON(ul_tbf, GPRS_RLCMAC_FLAG_PACCH, false);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span> ul_tbf->update_ms(tlli, GPRS_RLCMAC_UL_TBF);</span><br><span> TBF_SET_ASS_STATE_UL(ul_tbf, GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ);</span><br><span> ul_tbf->control_ts = ts;</span><br><span>@@ -252,14 +252,14 @@</span><br><span> frame->is_complete);</span><br><span> </span><br><span> m_llc.append_frame(data + frame->offset, frame->length);</span><br><span style="color: hsl(0, 100%, 40%);">- m_llc.consume(frame->length);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume(&m_llc, frame->length);</span><br><span> }</span><br><span> </span><br><span> if (frame->is_complete) {</span><br><span> /* send frame to SGSN */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPTBFUL(this, LOGL_DEBUG, "complete UL frame len=%d\n", m_llc.frame_length());</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPTBFUL(this, LOGL_DEBUG, "complete UL frame len=%d\n", llc_frame_length(&m_llc));</span><br><span> snd_ul_ud();</span><br><span style="color: hsl(0, 100%, 40%);">- bts->do_rate_ctr_add(CTR_LLC_UL_BYTES, m_llc.frame_length());</span><br><span style="color: hsl(120, 100%, 40%);">+ bts->do_rate_ctr_add(CTR_LLC_UL_BYTES, llc_frame_length(&m_llc));</span><br><span> m_llc.reset();</span><br><span> }</span><br><span> }</span><br><span>@@ -357,7 +357,7 @@</span><br><span> </span><br><span> /* store measurement values */</span><br><span> if (ms())</span><br><span style="color: hsl(0, 100%, 40%);">- ms()->update_l1_meas(meas);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_update_l1_meas(ms(), meas);</span><br><span> </span><br><span> uint32_t new_tlli = GSM_RESERVED_TMSI;</span><br><span> unsigned int block_idx;</span><br><span>@@ -559,10 +559,10 @@</span><br><span> {</span><br><span> uint8_t qos_profile[3];</span><br><span> struct msgb *llc_pdu;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + m_llc.frame_length();</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + llc_frame_length(&m_llc);</span><br><span> struct bssgp_bvc_ctx *bctx = gprs_bssgp_pcu_current_bctx();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), m_llc.frame_length());</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), llc_frame_length(&m_llc));</span><br><span> if (!bctx) {</span><br><span> LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");</span><br><span> m_llc.reset_frame_space();</span><br><span>@@ -570,8 +570,8 @@</span><br><span> }</span><br><span> </span><br><span> llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*m_llc.frame_length()));</span><br><span style="color: hsl(0, 100%, 40%);">- tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*m_llc.frame_length(), m_llc.frame);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*llc_frame_length(&m_llc)));</span><br><span style="color: hsl(120, 100%, 40%);">+ tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*llc_frame_length(&m_llc), m_llc.frame);</span><br><span> qos_profile[0] = QOS_PROFILE >> 16;</span><br><span> qos_profile[1] = QOS_PROFILE >> 8;</span><br><span> qos_profile[2] = QOS_PROFILE;</span><br><span>@@ -772,3 +772,11 @@</span><br><span> {</span><br><span> return &m_window;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_ul_tbf *as_ul_tbf(struct gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)</span><br><span style="color: hsl(120, 100%, 40%);">+ return static_cast<gprs_rlcmac_ul_tbf *>(tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/tbf_ul.h b/src/tbf_ul.h</span><br><span>index 9ccdf62..1d9cf50 100644</span><br><span>--- a/src/tbf_ul.h</span><br><span>+++ b/src/tbf_ul.h</span><br><span>@@ -108,32 +108,28 @@</span><br><span> gprs_rlc_ul_window m_window;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">-extern "C" {</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);</span><br><span style="color: hsl(0, 100%, 40%);">-void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);</span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __cplusplus</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> inline uint16_t gprs_rlcmac_ul_tbf::window_size() const</span><br><span> {</span><br><span> return m_window.ws();</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- return static_cast<gprs_rlcmac_ul_tbf *>(tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot);</span><br><span> struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, GprsMs *ms,</span><br><span> int8_t use_trx, uint32_t tlli);</span><br><span> struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,</span><br><span> GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#else /* ifdef __cplusplus */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_ul_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);</span><br><span style="color: hsl(120, 100%, 40%);">+void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gprs_rlcmac_ul_tbf *as_ul_tbf(struct gprs_rlcmac_tbf *tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> #endif</span><br><span>diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp</span><br><span>index 8ebf159..17cee46 100644</span><br><span>--- a/tests/alloc/AllocTest.cpp</span><br><span>+++ b/tests/alloc/AllocTest.cpp</span><br><span>@@ -224,12 +224,12 @@</span><br><span> return false;</span><br><span> </span><br><span> OSMO_ASSERT(ul_tbf->ms());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ul_tbf->ms()->current_trx());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_current_trx(ul_tbf->ms()));</span><br><span> </span><br><span> dump_assignment(ul_tbf, "UL", verbose);</span><br><span> </span><br><span> /* assume final ack has not been sent */</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = tbf_alloc_dl_tbf(bts, ms, ms->current_trx()->trx_no, false);</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = tbf_alloc_dl_tbf(bts, ms, ms_current_trx(ms)->trx_no, false);</span><br><span> if (!dl_tbf)</span><br><span> return false;</span><br><span> </span><br><span>@@ -268,11 +268,11 @@</span><br><span> </span><br><span> dl_tbf->update_ms(0x23, GPRS_RLCMAC_DL_TBF);</span><br><span> OSMO_ASSERT(dl_tbf->ms() == ms);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(dl_tbf->ms()->current_trx());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_current_trx(dl_tbf->ms()));</span><br><span> </span><br><span> dump_assignment(dl_tbf, "DL", verbose);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf = tbf_alloc_ul_tbf(bts, ms, ms->current_trx()->trx_no, false);</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_tbf = tbf_alloc_ul_tbf(bts, ms, ms_current_trx(ms)->trx_no, false);</span><br><span> if (!ul_tbf)</span><br><span> return false;</span><br><span> </span><br><span>@@ -319,8 +319,8 @@</span><br><span> return false;</span><br><span> </span><br><span> OSMO_ASSERT(ul_tbf->ms() == ms);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ul_tbf->ms()->current_trx());</span><br><span style="color: hsl(0, 100%, 40%);">- trx_no = ms->current_trx()->trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_current_trx(ul_tbf->ms()));</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_no = ms_current_trx(ms)->trx_no;</span><br><span> dump_assignment(ul_tbf, "UL", true);</span><br><span> </span><br><span> /* assume final ack has not been sent */</span><br><span>@@ -453,50 +453,55 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static GprsMs *alloc_tbfs(BTS *the_bts, GprsMs *ms, enum test_mode mode)</span><br><span style="color: hsl(120, 100%, 40%);">+static GprsMs *alloc_tbfs(BTS *the_bts, struct GprsMs *old_ms, enum test_mode mode)</span><br><span> {</span><br><span> struct gprs_rlcmac_bts *bts;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct GprsMs *ms, *new_ms;</span><br><span> uint8_t trx_no = -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(old_ms != NULL);</span><br><span> </span><br><span> bts = the_bts->bts_data();</span><br><span> </span><br><span> gprs_rlcmac_tbf *tbf = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ms && ms->current_trx())</span><br><span style="color: hsl(0, 100%, 40%);">- trx_no = ms->current_trx()->trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_current_trx(old_ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_no = ms_current_trx(old_ms)->trx_no;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard1(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(old_ms);</span><br><span> </span><br><span> /* Allocate what is needed first */</span><br><span> switch (mode) {</span><br><span> case TEST_MODE_UL_ONLY:</span><br><span> case TEST_MODE_DL_AFTER_UL:</span><br><span> case TEST_MODE_UL_AND_DL:</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->ul_tbf())</span><br><span style="color: hsl(0, 100%, 40%);">- tbf_free(ms->ul_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- tbf = tbf_alloc_ul_tbf(bts, ms, trx_no, false);</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_ul_tbf(old_ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free(ms_ul_tbf(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf = tbf_alloc_ul_tbf(bts, old_ms, trx_no, false);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(old_ms);</span><br><span> return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> break;</span><br><span> case TEST_MODE_DL_ONLY:</span><br><span> case TEST_MODE_UL_AFTER_DL:</span><br><span> case TEST_MODE_DL_AND_UL:</span><br><span style="color: hsl(0, 100%, 40%);">- if (ms->dl_tbf())</span><br><span style="color: hsl(0, 100%, 40%);">- tbf_free(ms->dl_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- tbf = tbf_alloc_dl_tbf(bts, ms, trx_no, false);</span><br><span style="color: hsl(0, 100%, 40%);">- if (tbf == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_dl_tbf(old_ms))</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free(ms_dl_tbf(old_ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf = tbf_alloc_dl_tbf(bts, old_ms, trx_no, false);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tbf == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(old_ms);</span><br><span> return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> OSMO_ASSERT(tbf);</span><br><span> OSMO_ASSERT(tbf->ms());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms == NULL || ms == tbf->ms());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(old_ms == tbf->ms());</span><br><span> ms = tbf->ms();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard2(ms);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ new_ms = ms;</span><br><span> /* Continue with what is needed next */</span><br><span> switch (mode) {</span><br><span> case TEST_MODE_UL_ONLY:</span><br><span>@@ -506,12 +511,12 @@</span><br><span> </span><br><span> case TEST_MODE_DL_AFTER_UL:</span><br><span> case TEST_MODE_UL_AND_DL:</span><br><span style="color: hsl(0, 100%, 40%);">- ms = alloc_tbfs(the_bts, ms, TEST_MODE_DL_ONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+ new_ms = alloc_tbfs(the_bts, ms, TEST_MODE_DL_ONLY);</span><br><span> break;</span><br><span> </span><br><span> case TEST_MODE_UL_AFTER_DL:</span><br><span> case TEST_MODE_DL_AND_UL:</span><br><span style="color: hsl(0, 100%, 40%);">- ms = alloc_tbfs(the_bts, ms, TEST_MODE_UL_ONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+ new_ms = alloc_tbfs(the_bts, ms, TEST_MODE_UL_ONLY);</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span>@@ -527,10 +532,12 @@</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ms && tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!new_ms && tbf)</span><br><span> tbf_free(tbf);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return guard2.is_idle() ? NULL : ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(old_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ return new_ms;</span><br><span> }</span><br><span> </span><br><span> static unsigned alloc_many_tbfs(BTS *the_bts, unsigned min_class,</span><br><span>@@ -556,16 +563,16 @@</span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> if (!ms)</span><br><span> ms = the_bts->ms_alloc(0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_ms_class(ms_class);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_ms_class(ms, ms_class);</span><br><span> ms = alloc_tbfs(the_bts, ms, mode);</span><br><span> if (!ms)</span><br><span> break;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ul_tbf = ms->ul_tbf();</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms->dl_tbf();</span><br><span style="color: hsl(0, 100%, 40%);">- trx = ms->current_trx();</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_tbf = ms_ul_tbf(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ trx = ms_current_trx(ms);</span><br><span> </span><br><span> OSMO_ASSERT(ul_tbf || dl_tbf);</span><br><span> </span><br><span>@@ -616,12 +623,12 @@</span><br><span> get_dir_char(0x80, ul_slots, dl_slots, busy_slots));</span><br><span> </span><br><span> if (tfi >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->current_trx());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_current_trx(ms));</span><br><span> tfi2 = the_bts->tfi_find_free(dir, &trx_no2,</span><br><span style="color: hsl(0, 100%, 40%);">- ms->current_trx()->trx_no);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_current_trx(ms)->trx_no);</span><br><span> OSMO_ASSERT(tfi != tfi2);</span><br><span> OSMO_ASSERT(tfi2 < 0 ||</span><br><span style="color: hsl(0, 100%, 40%);">- trx_no2 == ms->current_trx()->trx_no);</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_no2 == ms_current_trx(ms)->trx_no);</span><br><span> }</span><br><span> </span><br><span> ms_class += 1;</span><br><span>diff --git a/tests/app_info/AppInfoTest.cpp b/tests/app_info/AppInfoTest.cpp</span><br><span>index cd4454d..6e33538 100644</span><br><span>--- a/tests/app_info/AppInfoTest.cpp</span><br><span>+++ b/tests/app_info/AppInfoTest.cpp</span><br><span>@@ -152,9 +152,9 @@</span><br><span> {</span><br><span> fprintf(stderr, "--- %s ---\n", __func__);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free(tbf1);</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free(tbf2);</span><br><span> BTS::main_bts()->cleanup();</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(tbf1);</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(tbf2);</span><br><span> /* FIXME: talloc report disabled, because bts->ms_alloc() in prepare_bts_with_two_dl_tbf_subscr() causes leak */</span><br><span> /* talloc_report_full(tall_pcu_ctx, stderr); */</span><br><span> talloc_free(tall_pcu_ctx);</span><br><span>diff --git a/tests/app_info/AppInfoTest.err b/tests/app_info/AppInfoTest.err</span><br><span>index ae20ea3..9b0910f 100644</span><br><span>--- a/tests/app_info/AppInfoTest.err</span><br><span>+++ b/tests/app_info/AppInfoTest.err</span><br><span>@@ -52,3 +52,14 @@</span><br><span> Sending Packet Application Information to 2 subscribers with active TBF</span><br><span> </span><br><span> --- cleanup ---</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002.</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002.</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 6, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 1 TBFs, USFs = 00, TFIs = 00000002.</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.</span><br><span style="color: hsl(120, 100%, 40%);">+Detaching TBF from MS object, TLLI = 0xffffffff, TBF = TBF(TFI=0 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 5, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.</span><br><span style="color: hsl(120, 100%, 40%);">+PDCH(TS 6, TRX 0): Detaching TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.</span><br><span style="color: hsl(120, 100%, 40%);">+Detaching TBF from MS object, TLLI = 0xffffffff, TBF = TBF(TFI=1 TLLI=0xffffffff DIR=DL STATE=RELEASING EGPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+Destroying MS object, TLLI = 0xffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+Destroying MS object, TLLI = 0xffffffff</span><br><span>diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp</span><br><span>index 67ed2a7..8fa76dd 100644</span><br><span>--- a/tests/edge/EdgeTest.cpp</span><br><span>+++ b/tests/edge/EdgeTest.cpp</span><br><span>@@ -619,7 +619,7 @@</span><br><span> write_offset = 0;</span><br><span> memset(data, 0, sizeof(data));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 1);</span><br><span> </span><br><span> count_payload = -1;</span><br><span> </span><br><span>@@ -767,7 +767,7 @@</span><br><span> write_offset = 0;</span><br><span> memset(data, 0, sizeof(data));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 10);</span><br><span> count_payload = -1;</span><br><span> </span><br><span> ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,</span><br><span>@@ -899,7 +899,7 @@</span><br><span> write_offset = 0;</span><br><span> memset(data, 0, sizeof(data));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 0);</span><br><span> count_payload = -1;</span><br><span> </span><br><span> ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,</span><br><span>@@ -1167,7 +1167,6 @@</span><br><span> uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,</span><br><span> uint8_t ms_class)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct pcu_l1_meas meas;</span><br><span> int tfi = 0;</span><br><span> uint8_t data[79] = {0};</span><br><span> struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;</span><br><span>diff --git a/tests/llc/LlcTest.cpp b/tests/llc/LlcTest.cpp</span><br><span>index 10cd96b..bfcac77 100644</span><br><span>--- a/tests/llc/LlcTest.cpp</span><br><span>+++ b/tests/llc/LlcTest.cpp</span><br><span>@@ -60,10 +60,10 @@</span><br><span> }</span><br><span> </span><br><span> static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data,</span><br><span style="color: hsl(0, 100%, 40%);">- size_t len, const gprs_llc_queue::MetaInfo *exp_info)</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t len, const MetaInfo *exp_info)</span><br><span> {</span><br><span> struct msgb *llc_msg;</span><br><span style="color: hsl(0, 100%, 40%);">- const gprs_llc_queue::MetaInfo *info_res;</span><br><span style="color: hsl(120, 100%, 40%);">+ const MetaInfo *info_res;</span><br><span> </span><br><span> llc_msg = queue->dequeue(&info_res);</span><br><span> OSMO_ASSERT(llc_msg != NULL);</span><br><span>@@ -88,7 +88,7 @@</span><br><span> }</span><br><span> </span><br><span> static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message,</span><br><span style="color: hsl(0, 100%, 40%);">- const gprs_llc_queue::MetaInfo *exp_info = 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ const MetaInfo *exp_info = 0)</span><br><span> {</span><br><span> dequeue_and_check(queue,</span><br><span> (uint8_t *)(exp_message), strlen(exp_message), exp_info);</span><br><span>@@ -101,33 +101,33 @@</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue.init();</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_init(&queue);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 0);</span><br><span> </span><br><span> enqueue_data(&queue, "LLC message", &expire_time);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 11);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 11);</span><br><span> </span><br><span> enqueue_data(&queue, "other LLC message", &expire_time);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 28);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 28);</span><br><span> </span><br><span> dequeue_and_check(&queue, "LLC message");</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 17);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 17);</span><br><span> </span><br><span> dequeue_and_check(&queue, "other LLC message");</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 0);</span><br><span> </span><br><span> enqueue_data(&queue, "LLC", &expire_time);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 3);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue.clear(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_clear(&queue, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 0);</span><br><span> </span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -135,14 +135,14 @@</span><br><span> static void test_llc_meta()</span><br><span> {</span><br><span> gprs_llc_queue queue;</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_llc_queue::MetaInfo info1 = {0};</span><br><span style="color: hsl(0, 100%, 40%);">- gprs_llc_queue::MetaInfo info2 = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+ MetaInfo info1 = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+ MetaInfo info2 = {0};</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue.init();</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_init(&queue);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 0);</span><br><span> </span><br><span> info1.recv_time.tv_sec = 123456777;</span><br><span> info1.recv_time.tv_nsec = 123456000;</span><br><span>@@ -161,9 +161,9 @@</span><br><span> dequeue_and_check(&queue, "LLC message 1", &info1);</span><br><span> dequeue_and_check(&queue, "LLC message 2", &info2);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue.clear(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_clear(&queue, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue) == 0);</span><br><span> </span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -176,8 +176,8 @@</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue1.init();</span><br><span style="color: hsl(0, 100%, 40%);">- queue2.init();</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_init(&queue1);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_init(&queue2);</span><br><span> </span><br><span> clk_mono_override_time->tv_sec += 1;</span><br><span> enqueue_data(&queue1, "*A*", &expire_time);</span><br><span>@@ -194,17 +194,17 @@</span><br><span> clk_mono_override_time->tv_sec += 1;</span><br><span> enqueue_data(&queue2, "*E*", &expire_time);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue1.size() == 3);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue1.octets() == 9);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.size() == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.octets() == 6);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue1) == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue1) == 9);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue2) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue2) == 6);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- queue2.move_and_merge(&queue1);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_queue_move_and_merge(&queue2, &queue1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue1.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue1.octets() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.size() == 5);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.octets() == 15);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue2) == 5);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue2) == 15);</span><br><span> </span><br><span> dequeue_and_check(&queue2, "*A*");</span><br><span> dequeue_and_check(&queue2, "*B*");</span><br><span>@@ -212,8 +212,8 @@</span><br><span> dequeue_and_check(&queue2, "*D*");</span><br><span> dequeue_and_check(&queue2, "*E*");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(queue2.octets() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(&queue2) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_octets(&queue2) == 0);</span><br><span> </span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span>diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp</span><br><span>index 4f47bc9..c164409 100644</span><br><span>--- a/tests/ms/MsTest.cpp</span><br><span>+++ b/tests/ms/MsTest.cpp</span><br><span>@@ -56,33 +56,33 @@</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> </span><br><span> dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms);</span><br><span> ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_UL_TBF) == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_DL_TBF) == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_UL_TBF) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_DL_TBF) == dl_tbf);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, dl_tbf);</span><br><span> /* The ms object is freed now */</span><br><span> ms = NULL;</span><br><span> </span><br><span>@@ -92,6 +92,23 @@</span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static enum {CB_UNKNOWN, CB_IS_IDLE, CB_IS_ACTIVE} last_cb = CB_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_idle_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" ms_idle() was called\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_IS_IDLE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_active_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" ms_active() was called\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_IS_ACTIVE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gpr_ms_callback ms_cb = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_idle = ms_idle_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_active = ms_active_cb</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span> static void test_ms_callback()</span><br><span> {</span><br><span> uint32_t tlli = 0xffeeddbb;</span><br><span>@@ -99,63 +116,50 @@</span><br><span> gprs_rlcmac_ul_tbf *ul_tbf;</span><br><span> BTS the_bts;</span><br><span> GprsMs *ms;</span><br><span style="color: hsl(0, 100%, 40%);">- static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct MyCallback: public GprsMs::Callback {</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_idle() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = IS_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_active() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = IS_ACTIVE;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_callback(&cb);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_callback(ms, &ms_cb);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> </span><br><span> dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms);</span><br><span> ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == IS_ACTIVE);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_IS_ACTIVE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == IS_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_IS_IDLE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span> </span><br><span> talloc_free(dl_tbf);</span><br><span> talloc_free(ul_tbf);</span><br><span>@@ -163,6 +167,22 @@</span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static bool was_idle;</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_replace_tbf_idle_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" ms_idle() was called\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ was_idle = true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static void ms_replace_tbf_active_cb(struct GprsMs *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" ms_active() was called\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gpr_ms_callback ms_replace_tbf_cb = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_idle = ms_replace_tbf_idle_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ms_active = ms_replace_tbf_active_cb</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span> static void test_ms_replace_tbf()</span><br><span> {</span><br><span> uint32_t tlli = 0xffeeddbb;</span><br><span>@@ -170,26 +190,13 @@</span><br><span> gprs_rlcmac_ul_tbf *ul_tbf;</span><br><span> BTS the_bts;</span><br><span> GprsMs *ms;</span><br><span style="color: hsl(0, 100%, 40%);">- static bool was_idle;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct MyCallback: public GprsMs::Callback {</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_idle() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- was_idle = true;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_active() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } cb;</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_callback(&cb);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_callback(ms, &ms_replace_tbf_cb);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> was_idle = false;</span><br><span> </span><br><span> dl_tbf[0] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span>@@ -199,49 +206,49 @@</span><br><span> ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf[0]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf[0]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(!was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(!was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(!was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(!was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(dl_tbf[0]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, dl_tbf[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(!was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(dl_tbf[1]);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llist_empty(&ms->old_tbfs()));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, dl_tbf[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llist_empty(&ms->old_tbfs));</span><br><span> OSMO_ASSERT(was_idle);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span> </span><br><span> talloc_free(dl_tbf[0]);</span><br><span> talloc_free(dl_tbf[1]);</span><br><span>@@ -260,86 +267,86 @@</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, start_tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> </span><br><span> /* MS announces TLLI, SGSN uses it immediately */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span> /* MS announces TLLI, SGSN uses it later */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(start_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, start_tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(start_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span> /* MS announces TLLI, SGSN uses it later after another new TLLI */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(start_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, start_tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(other_sgsn_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, other_sgsn_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, other_sgsn_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, other_sgsn_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->check_tlli(start_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_check_tlli(ms, start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_check_tlli(ms, other_sgsn_tlli));</span><br><span> </span><br><span> /* SGSN uses the new TLLI before it is announced by the MS (shouldn't</span><br><span> * happen in normal use) */</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(start_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, start_tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == start_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == start_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == new_ms_tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->check_tlli(new_ms_tlli));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->check_tlli(start_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == new_ms_tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_check_tlli(ms, start_tlli));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span> </span><br><span> printf("=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -353,9 +360,9 @@</span><br><span> ms = st->create_ms();</span><br><span> </span><br><span> if (dir == GPRS_RLCMAC_UL_TBF)</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_tlli(ms, tlli);</span><br><span> else</span><br><span style="color: hsl(0, 100%, 40%);">- ms->confirm_tlli(tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_confirm_tlli(ms, tlli);</span><br><span> </span><br><span> return ms;</span><br><span> }</span><br><span>@@ -378,44 +385,44 @@</span><br><span> </span><br><span> ms = prepare_ms(&store, tlli + 0, GPRS_RLCMAC_UL_TBF);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == tlli + 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_imsi(imsi1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == tlli + 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(ms, imsi1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms), imsi1) == 0);</span><br><span> </span><br><span> ms_tmp = store.get_ms(tlli + 0);</span><br><span> OSMO_ASSERT(ms == ms_tmp);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == tlli + 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == tlli + 0);</span><br><span> </span><br><span> ms_tmp = store.get_ms(0, 0, imsi1);</span><br><span> OSMO_ASSERT(ms == ms_tmp);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms), imsi1) == 0);</span><br><span> ms_tmp = store.get_ms(0, 0, imsi2);</span><br><span> OSMO_ASSERT(ms_tmp == NULL);</span><br><span> </span><br><span> ms = prepare_ms(&store, tlli + 1, GPRS_RLCMAC_UL_TBF);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == tlli + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_imsi(imsi2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == tlli + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(ms, imsi2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms), imsi2) == 0);</span><br><span> </span><br><span> ms_tmp = store.get_ms(tlli + 1);</span><br><span> OSMO_ASSERT(ms == ms_tmp);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->tlli() == tlli + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_tlli(ms) == tlli + 1);</span><br><span> </span><br><span> ms_tmp = store.get_ms(0, 0, imsi1);</span><br><span> OSMO_ASSERT(ms_tmp != NULL);</span><br><span> OSMO_ASSERT(ms_tmp != ms);</span><br><span> ms_tmp = store.get_ms(0, 0, imsi2);</span><br><span> OSMO_ASSERT(ms == ms_tmp);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms), imsi2) == 0);</span><br><span> </span><br><span> /* delete ms */</span><br><span> ms = store.get_ms(tlli + 0);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span> ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span> ms = store.get_ms(tlli + 0);</span><br><span> OSMO_ASSERT(ms == NULL);</span><br><span> ms = store.get_ms(tlli + 1);</span><br><span>@@ -424,8 +431,8 @@</span><br><span> /* delete ms */</span><br><span> ms = store.get_ms(tlli + 1);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span> ms = store.get_ms(tlli + 1);</span><br><span> OSMO_ASSERT(ms == NULL);</span><br><span> </span><br><span>@@ -441,62 +448,49 @@</span><br><span> gprs_rlcmac_ul_tbf *ul_tbf;</span><br><span> BTS the_bts;</span><br><span> GprsMs *ms;</span><br><span style="color: hsl(0, 100%, 40%);">- static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct MyCallback: public GprsMs::Callback {</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_idle(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_idle() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = IS_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- virtual void ms_active(class GprsMs *ms) {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- printf(" ms_active() was called\n");</span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = IS_ACTIVE;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_callback(&cb);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->set_timeout(1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_callback(ms, &ms_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_timeout(ms, 1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> </span><br><span> dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms);</span><br><span> ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);</span><br><span> new (ul_tbf) gprs_rlcmac_ul_tbf(&the_bts, ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == IS_ACTIVE);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_IS_ACTIVE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(ul_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms->detach_tbf(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == UNKNOWN);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_detach_tbf(ms, dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_UNKNOWN);</span><br><span> </span><br><span> usleep(1100000);</span><br><span> osmo_timers_update();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(last_cb == IS_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(last_cb == CB_IS_IDLE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- last_cb = UNKNOWN;</span><br><span style="color: hsl(0, 100%, 40%);">- delete ms;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_cb = CB_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ms);</span><br><span> talloc_free(dl_tbf);</span><br><span> talloc_free(ul_tbf);</span><br><span> </span><br><span>@@ -519,21 +513,21 @@</span><br><span> bts->cs_downgrade_threshold = 0;</span><br><span> bts->cs_adj_lower_limit = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms = ms_alloc(&the_bts, tlli);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_is_idle(ms));</span><br><span> </span><br><span> dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->attach_tbf(dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms, dl_tbf);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->is_idle());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_is_idle(ms));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(mcs_chan_code(ms_current_cs_dl(ms)) == 3);</span><br><span> </span><br><span> bts->cs_downgrade_threshold = 200;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(mcs_chan_code(ms_current_cs_dl(ms)) == 2);</span><br><span> </span><br><span> talloc_free(dl_tbf);</span><br><span> </span><br><span>@@ -543,10 +537,10 @@</span><br><span> static void dump_ms(const GprsMs *ms, const char *pref)</span><br><span> {</span><br><span> printf("%s MS DL %s/%s, UL %s/%s, mode %s, <%s>\n", pref,</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(ms->current_cs_dl()), mcs_name(ms->max_cs_dl()),</span><br><span style="color: hsl(0, 100%, 40%);">- mcs_name(ms->current_cs_ul()), mcs_name(ms->max_cs_ul()),</span><br><span style="color: hsl(0, 100%, 40%);">- mode_name(ms->mode()),</span><br><span style="color: hsl(0, 100%, 40%);">- ms->is_idle() ? "IDLE" : "ACTIVE");</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms_current_cs_dl(ms)), mcs_name(ms_max_cs_dl(ms)),</span><br><span style="color: hsl(120, 100%, 40%);">+ mcs_name(ms_current_cs_ul(ms)), mcs_name(ms_max_cs_ul(ms)),</span><br><span style="color: hsl(120, 100%, 40%);">+ mode_name(ms_mode(ms)),</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_is_idle(ms) ? "IDLE" : "ACTIVE");</span><br><span> }</span><br><span> </span><br><span> static void test_ms_mcs_mode()</span><br><span>@@ -560,48 +554,48 @@</span><br><span> </span><br><span> printf("=== start %s ===\n", __func__);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms1 = new GprsMs(&the_bts, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms1 = ms_alloc(&the_bts, tlli);</span><br><span> dump_ms(ms1, "1: no BTS defaults ");</span><br><span> </span><br><span> bts->initial_cs_dl = 4;</span><br><span> bts->initial_cs_ul = 1;</span><br><span> bts->cs_downgrade_threshold = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms2 = new GprsMs(&the_bts, tlli + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms2 = ms_alloc(&the_bts, tlli + 1);</span><br><span> dump_ms(ms2, "2: with BTS defaults");</span><br><span> </span><br><span> dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);</span><br><span> new (dl_tbf) gprs_rlcmac_dl_tbf(&the_bts, ms2);</span><br><span style="color: hsl(0, 100%, 40%);">- ms2->attach_tbf(dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_attach_tbf(ms2, dl_tbf);</span><br><span> </span><br><span> dump_ms(ms2, "2: after TBF attach ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms1->set_mode(EGPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms1, EGPRS);</span><br><span> dump_ms(ms1, "1: after mode set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms2->set_mode(EGPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms2, EGPRS);</span><br><span> dump_ms(ms2, "2: after mode set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms1->set_current_cs_dl(MCS7);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(ms1, MCS7);</span><br><span> dump_ms(ms1, "1: after MCS set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms2->set_current_cs_dl(MCS8);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(ms2, MCS8);</span><br><span> dump_ms(ms2, "2: after MCS set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms1->set_mode(EGPRS_GMSK);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms1, EGPRS_GMSK);</span><br><span> dump_ms(ms1, "1: after mode set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms2->set_mode(EGPRS_GMSK);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms2, EGPRS_GMSK);</span><br><span> dump_ms(ms2, "2: after mode set ");</span><br><span> </span><br><span> // FIXME: following code triggers ASAN failure:</span><br><span> // ms2->detach_tbf(dl_tbf);</span><br><span> // dump_ms(ms2, "2: after TBF detach ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms1->set_mode(GPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms1, GPRS);</span><br><span> dump_ms(ms1, "1: after mode set ");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ms2->set_mode(GPRS);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_mode(ms2, GPRS);</span><br><span> dump_ms(ms2, "2: after mode set ");</span><br><span> </span><br><span> talloc_free(dl_tbf);</span><br><span>diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp</span><br><span>index 1a1dc6f..e6041a3 100644</span><br><span>--- a/tests/tbf/TbfTest.cpp</span><br><span>+++ b/tests/tbf/TbfTest.cpp</span><br><span>@@ -109,14 +109,14 @@</span><br><span> OSMO_ASSERT(dl_tbf != NULL);</span><br><span> dl_tbf->update_ms(0x2342, GPRS_RLCMAC_DL_TBF);</span><br><span> dl_tbf->set_ta(4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span> OSMO_ASSERT(dl_tbf->ms() == ms);</span><br><span> </span><br><span> gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(the_bts.bts_data(),</span><br><span> ms, 0, false);</span><br><span> OSMO_ASSERT(ul_tbf != NULL);</span><br><span> ul_tbf->update_ms(0x2342, GPRS_RLCMAC_UL_TBF);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> OSMO_ASSERT(ul_tbf->ms() == ms);</span><br><span> </span><br><span> OSMO_ASSERT(the_bts.ms_by_tlli(0x2342) == ms);</span><br><span>@@ -133,8 +133,8 @@</span><br><span> </span><br><span> ms_new = the_bts.ms_by_tlli(0x4232);</span><br><span> OSMO_ASSERT(ms == ms_new);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> /* Now use the new TLLI for UL */</span><br><span> ul_tbf->update_ms(0x4232, GPRS_RLCMAC_UL_TBF);</span><br><span>@@ -143,7 +143,7 @@</span><br><span> </span><br><span> ms_new = the_bts.ms_by_tlli(0x4232);</span><br><span> OSMO_ASSERT(ms_new != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms_new->ta() == 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms_new) == 4);</span><br><span> </span><br><span> OSMO_ASSERT(ul_tbf->ta() == 4);</span><br><span> OSMO_ASSERT(dl_tbf->ta() == 4);</span><br><span>@@ -298,25 +298,27 @@</span><br><span> </span><br><span> /* Clean up and ensure tbfs are in the correct state */</span><br><span> OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));</span><br><span style="color: hsl(0, 100%, 40%);">- new_tbf = ms->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ new_tbf = ms_dl_tbf(ms);</span><br><span> check_tbf(new_tbf);</span><br><span> OSMO_ASSERT(new_tbf != dl_tbf);</span><br><span> OSMO_ASSERT(new_tbf->tfi() == 1);</span><br><span> check_tbf(dl_tbf);</span><br><span> TBF_SET_ASS_STATE_DL(dl_tbf, GPRS_RLCMAC_DL_ASS_NONE);</span><br><span> if (test_mode == TEST_MODE_REVERSE_FREE) {</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span> tbf_free(new_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span> check_tbf(dl_tbf);</span><br><span> tbf_free(dl_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span> } else {</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms);</span><br><span> tbf_free(dl_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == new_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == new_tbf);</span><br><span> check_tbf(new_tbf);</span><br><span> tbf_free(new_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms);</span><br><span> }</span><br><span> </span><br><span> fprintf(stderr, "=== end %s ===\n", __func__);</span><br><span>@@ -421,32 +423,33 @@</span><br><span> dl_tbf[0]->update_ms(0xf1000001, GPRS_RLCMAC_DL_TBF);</span><br><span> dl_tbf[1]->update_ms(0xf1000002, GPRS_RLCMAC_DL_TBF);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf[0]->ms()->set_imsi("001001000000001");</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(dl_tbf[0]->ms(), "001001000000001");</span><br><span> ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000001");</span><br><span> OSMO_ASSERT(ms1 != NULL);</span><br><span> ms2 = the_bts.ms_store().get_ms(0xf1000001);</span><br><span> OSMO_ASSERT(ms2 != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms2->imsi(), "001001000000001") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000001") == 0);</span><br><span> OSMO_ASSERT(ms1 == ms2);</span><br><span> </span><br><span> /* change the IMSI on TBF 0 */</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf[0]->ms()->set_imsi("001001000000002");</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(dl_tbf[0]->ms(), "001001000000002");</span><br><span> ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000001");</span><br><span> OSMO_ASSERT(ms1 == NULL);</span><br><span> ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002");</span><br><span> OSMO_ASSERT(ms1 != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms2->imsi(), "001001000000002") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms2), "001001000000002") == 0);</span><br><span> OSMO_ASSERT(ms1 == ms2);</span><br><span> </span><br><span> /* use the same IMSI on TBF 1 */</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- GprsMs::Guard guard(ms2);</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf[1]->ms()->set_imsi("001001000000002");</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_ref(ms2);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_imsi(dl_tbf[1]->ms(), "001001000000002");</span><br><span> ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002");</span><br><span> OSMO_ASSERT(ms1 != NULL);</span><br><span> OSMO_ASSERT(ms1 != ms2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms1->imsi(), "001001000000002") == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(strcmp(ms2->imsi(), "") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms1), "001001000000002") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(strcmp(ms_imsi(ms2), "") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_unref(ms2);</span><br><span> }</span><br><span> </span><br><span> ms2 = the_bts.ms_store().get_ms(0xf1000001);</span><br><span>@@ -539,8 +542,8 @@</span><br><span> </span><br><span> ms = the_bts.ms_store().get_ms(0, 0, imsi);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ms->dl_tbf()->set_ta(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_dl_tbf(ms)->set_ta(0);</span><br><span> </span><br><span> /* Handle LLC frame 2 */</span><br><span> memset(buf, 2, sizeof(buf));</span><br><span>@@ -549,7 +552,7 @@</span><br><span> OSMO_ASSERT(rc >= 0);</span><br><span> </span><br><span> /* TBF establishment fails (timeout) */</span><br><span style="color: hsl(0, 100%, 40%);">- tbf_free(ms->dl_tbf());</span><br><span style="color: hsl(120, 100%, 40%);">+ tbf_free(ms_dl_tbf(ms));</span><br><span> </span><br><span> /* Handle LLC frame 3 */</span><br><span> memset(buf, 3, sizeof(buf));</span><br><span>@@ -557,7 +560,7 @@</span><br><span> delay_csec, buf, sizeof(buf));</span><br><span> OSMO_ASSERT(rc >= 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) != NULL);</span><br><span> </span><br><span> /* Get first BSN */</span><br><span> struct msgb *msg;</span><br><span>@@ -572,8 +575,8 @@</span><br><span> 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- while (ms->dl_tbf()->have_data()) {</span><br><span style="color: hsl(0, 100%, 40%);">- msg = ms->dl_tbf()->create_dl_acked_block(fn += 4, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (ms_dl_tbf(ms)->have_data()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = ms_dl_tbf(ms)->create_dl_acked_block(fn += 4, 7);</span><br><span> fprintf(stderr, "MSG = %s\n", msgb_hexdump(msg));</span><br><span> if (!msgb_eq_data_print(msg, exp[expected_data - 1], GSM_MACBLOCK_LEN))</span><br><span> fprintf(stderr, "%s failed at %u\n", __func__, expected_data);</span><br><span>@@ -742,8 +745,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> /*</span><br><span> * TS 44.060, B.8.1</span><br><span>@@ -890,8 +893,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> /*</span><br><span> * TS 44.060, B.8.1</span><br><span>@@ -1386,8 +1389,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> return ul_tbf;</span><br><span> }</span><br><span>@@ -1469,8 +1472,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> return ul_tbf;</span><br><span> }</span><br><span>@@ -1554,8 +1557,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> return ul_tbf;</span><br><span> }</span><br><span>@@ -1637,8 +1640,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> return ul_tbf;</span><br><span> }</span><br><span>@@ -1655,7 +1658,7 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_imsi(imsi);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf() != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms) != NULL);</span><br><span> </span><br><span> if (imsi[0] && strcmp(imsi, "000") != 0) {</span><br><span> ms2 = the_bts->ms_by_tlli(tlli);</span><br><span>@@ -1672,7 +1675,7 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms);</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms);</span><br><span> OSMO_ASSERT(dl_tbf);</span><br><span> </span><br><span> while (dl_tbf->have_data()) {</span><br><span>@@ -1692,7 +1695,7 @@</span><br><span> {</span><br><span> fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());</span><br><span> if (print_ms)</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ul_tbf->ms()->tlli(), ul_tbf->ms()->ta());</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms_tlli(ul_tbf->ms()), ms_ta(ul_tbf->ms()));</span><br><span> }</span><br><span> </span><br><span> static void test_tbf_single_phase()</span><br><span>@@ -1866,10 +1869,10 @@</span><br><span> fprintf(stderr, "=== end %s ===\n", __func__);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static inline void print_ms(const GprsMs *ms, bool old)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void print_ms(GprsMs *ms, bool old)</span><br><span> {</span><br><span> fprintf(stderr, "%s MS: TLLI = 0x%08x, TA = %d, IMSI = %s, LLC = %zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">- old ? "Old" : "New", ms->tlli(), ms->ta(), ms->imsi(), ms->llc_queue()->size());</span><br><span style="color: hsl(120, 100%, 40%);">+ old ? "Old" : "New", ms_tlli(ms), ms_ta(ms), ms_imsi(ms), llc_queue_size(ms_llc_queue(ms)));</span><br><span> }</span><br><span> </span><br><span> static void test_tbf_ra_update_rach()</span><br><span>@@ -1905,9 +1908,9 @@</span><br><span> send_control_ack(ul_tbf);</span><br><span> </span><br><span> /* Make sure the RAU Accept gets sent to the MS */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->llc_queue()->size() == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 1);</span><br><span> transmit_dl_data(&the_bts, tlli1, &fn);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->llc_queue()->size() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0);</span><br><span> </span><br><span> /* Now establish a new TBF for the RA UPDATE COMPLETE (new TLLI) */</span><br><span> ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli2, &fn, qta,</span><br><span>@@ -1963,8 +1966,8 @@</span><br><span> send_dl_data(&the_bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20);</span><br><span> print_ms(ms1, true);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->llc_queue()->size() == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms1->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms1);</span><br><span> OSMO_ASSERT(dl_tbf != NULL);</span><br><span> </span><br><span> /* Get rid of old UL TBF */</span><br><span>@@ -1986,10 +1989,10 @@</span><br><span> OSMO_ASSERT(ms2 == ms);</span><br><span> </span><br><span> /* A DL TBF should still exist */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->dl_tbf());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms));</span><br><span> </span><br><span> /* No queued packets should be lost */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->llc_queue()->size() == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2);</span><br><span> </span><br><span> fprintf(stderr, "=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -2022,8 +2025,8 @@</span><br><span> send_dl_data(&the_bts, tlli1, imsi, (const uint8_t *)"DATA 2 *************", 20);</span><br><span> print_ms(ms1, true);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->llc_queue()->size() == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf = ms1->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf = ms_dl_tbf(ms1);</span><br><span> OSMO_ASSERT(dl_tbf != NULL);</span><br><span> </span><br><span> /* Get rid of old UL TBF */</span><br><span>@@ -2045,10 +2048,10 @@</span><br><span> OSMO_ASSERT(ms1 != ms);</span><br><span> </span><br><span> /* DL TBF should be removed */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!ms->dl_tbf());</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!ms_dl_tbf(ms));</span><br><span> </span><br><span> /* No queued packets should be lost */</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->llc_queue()->size() == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms)) == 2);</span><br><span> </span><br><span> fprintf(stderr, "=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -2099,11 +2102,11 @@</span><br><span> </span><br><span> /* Transmit all data */</span><br><span> transmit_dl_data(&the_bts, tlli1, &fn);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->llc_queue()->size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->dl_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms1->dl_tbf()->state_is(GPRS_RLCMAC_FINISHED));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms1)) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms1));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms1)->state_is(GPRS_RLCMAC_FINISHED));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf1 = ms1->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf1 = ms_dl_tbf(ms1);</span><br><span> </span><br><span> /* Send some LLC frames */</span><br><span> for (i = 0; i < 10; i++) {</span><br><span>@@ -2132,10 +2135,10 @@</span><br><span> </span><br><span> ms2 = the_bts.ms_by_tlli(tlli1);</span><br><span> OSMO_ASSERT(ms2 == ms1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms2->dl_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_ASSIGN));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms2));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_ASSIGN));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf2 = ms2->dl_tbf();</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_tbf2 = ms_dl_tbf(ms2);</span><br><span> </span><br><span> OSMO_ASSERT(dl_tbf1 != dl_tbf2);</span><br><span> </span><br><span>@@ -2144,9 +2147,9 @@</span><br><span> </span><br><span> /* Transmit all data */</span><br><span> transmit_dl_data(&the_bts, tlli1, &fn);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms2->llc_queue()->size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms2->dl_tbf());</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_FINISHED));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_queue_size(ms_llc_queue(ms2)) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms2));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_dl_tbf(ms2)->state_is(GPRS_RLCMAC_FINISHED));</span><br><span> </span><br><span> fprintf(stderr, "=== end %s ===\n", __func__);</span><br><span> }</span><br><span>@@ -2411,8 +2414,8 @@</span><br><span> </span><br><span> ms = the_bts->ms_by_tlli(tlli);</span><br><span> OSMO_ASSERT(ms != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ta() == qta/4);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ms->ul_tbf() == ul_tbf);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ta(ms) == qta/4);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf);</span><br><span> </span><br><span> egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;</span><br><span> egprs3->si = 0;</span><br><span>@@ -2799,9 +2802,7 @@</span><br><span> </span><br><span> OSMO_ASSERT(bsn1 == 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf->ms()->set_current_cs_dl</span><br><span style="color: hsl(0, 100%, 40%);">- (static_cast < enum CodingScheme ></span><br><span style="color: hsl(0, 100%, 40%);">- (CS4 + demanded_mcs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));</span><br><span> </span><br><span> fn = fn_add_blocks(fn, 1);</span><br><span> </span><br><span>@@ -2831,9 +2832,7 @@</span><br><span> OSMO_ASSERT(egprs3->cps == 3);</span><br><span> </span><br><span> /* Handle (MCS3, MCS3) -> MCS6 case */</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf->ms()->set_current_cs_dl</span><br><span style="color: hsl(0, 100%, 40%);">- (static_cast < enum CodingScheme ></span><br><span style="color: hsl(0, 100%, 40%);">- (CS4 + mcs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + mcs));</span><br><span> </span><br><span> NACK(dl_tbf, 0);</span><br><span> </span><br><span>@@ -2880,9 +2879,7 @@</span><br><span> </span><br><span> NACK(dl_tbf, 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf->ms()->set_current_cs_dl</span><br><span style="color: hsl(0, 100%, 40%);">- (static_cast < enum CodingScheme ></span><br><span style="color: hsl(0, 100%, 40%);">- (CS4 + demanded_mcs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));</span><br><span> </span><br><span> fn = fn_add_blocks(fn, 1);</span><br><span> </span><br><span>@@ -2967,9 +2964,7 @@</span><br><span> NACK(dl_tbf, 1);</span><br><span> </span><br><span> /* Set the demanded MCS to demanded_mcs */</span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf->ms()->set_current_cs_dl</span><br><span style="color: hsl(0, 100%, 40%);">- (static_cast < enum CodingScheme ></span><br><span style="color: hsl(0, 100%, 40%);">- (CS4 + demanded_mcs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));</span><br><span> </span><br><span> fn = fn_add_blocks(fn, 1);</span><br><span> /* Retransmit the first RLC data block with demanded_mcs */</span><br><span>@@ -2994,9 +2989,7 @@</span><br><span> NACK(dl_tbf, 0);</span><br><span> NACK(dl_tbf, 1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- dl_tbf->ms()->set_current_cs_dl</span><br><span style="color: hsl(0, 100%, 40%);">- (static_cast < enum CodingScheme ></span><br><span style="color: hsl(0, 100%, 40%);">- (CS4 + demanded_mcs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_set_current_cs_dl(dl_tbf->ms(), static_cast < enum CodingScheme > (CS4 + demanded_mcs));</span><br><span> </span><br><span> fn = fn_add_blocks(fn, 1);</span><br><span> /* Send first, second RLC data blocks with demanded_mcs */</span><br><span>@@ -3264,8 +3257,8 @@</span><br><span> pcu_vty_init();</span><br><span> </span><br><span> /* Initialize shared UL measurements */</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_link_qual(12);</span><br><span style="color: hsl(0, 100%, 40%);">- meas.set_rssi(31);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_link_qual(&meas, 12);</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_l1_meas_set_rssi(&meas, 31);</span><br><span> </span><br><span> test_tbf_base();</span><br><span> test_tbf_tlli_update();</span><br><span>diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp</span><br><span>index f224146..bc24b30 100644</span><br><span>--- a/tests/types/TypesTest.cpp</span><br><span>+++ b/tests/types/TypesTest.cpp</span><br><span>@@ -58,27 +58,27 @@</span><br><span> gprs_llc llc;</span><br><span> llc.init();</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.frame_length() == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_frame_length(&llc) == 0);</span><br><span> </span><br><span> llc.put_frame(data, 2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.frame_length() == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_frame_length(&llc) == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 2);</span><br><span> OSMO_ASSERT(llc.frame[0] == 1);</span><br><span> OSMO_ASSERT(llc.frame[1] == 2);</span><br><span> </span><br><span> llc.append_frame(&data[3], 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 3);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.frame_length() == 3);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_frame_length(&llc) == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 3);</span><br><span> </span><br><span> /* consume two bytes */</span><br><span style="color: hsl(0, 100%, 40%);">- llc.consume(&out, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.remaining_space() == LLC_MAX_LEN - 3);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.frame_length() == 3);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.chunk_size() == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ llc_consume_data(&llc, &out, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_remaining_space(&llc) == LLC_MAX_LEN - 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_frame_length(&llc) == 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_chunk_size(&llc) == 2);</span><br><span> </span><br><span> /* check that the bytes are as we expected */</span><br><span> OSMO_ASSERT(llc.frame[0] == 1);</span><br><span>@@ -86,9 +86,9 @@</span><br><span> OSMO_ASSERT(llc.frame[2] == 4);</span><br><span> </span><br><span> /* now fill the frame */</span><br><span style="color: hsl(0, 100%, 40%);">- llc.append_frame(data, llc.remaining_space() - 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(llc.fits_in_current_frame(1));</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(!llc.fits_in_current_frame(2));</span><br><span style="color: hsl(120, 100%, 40%);">+ llc.append_frame(data, llc_remaining_space(&llc) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(llc_fits_in_current_frame(&llc, 1));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!llc_fits_in_current_frame(&llc, 2));</span><br><span> }</span><br><span> }</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21748">change 21748</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-pcu/+/21748"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c </div>
<div style="display:none"> Gerrit-Change-Number: 21748 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>