pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmo-gprs/+/34044 )


Change subject: rlcmac: Fix rfn->fn calculation
......................................................................

rlcmac: Fix rfn->fn calculation

Change-Id: I00741289333853a8db472950ee2ac38dc2c74fd3
---
M include/osmocom/gprs/rlcmac/rlcmac_dec.h
M src/rlcmac/rlcmac_dec.c
M tests/rlcmac/Makefile.am
A tests/rlcmac/rlcmac_types_test.c
A tests/rlcmac/rlcmac_types_test.err
A tests/rlcmac/rlcmac_types_test.ok
M tests/testsuite.at
7 files changed, 189 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/44/34044/1

diff --git a/include/osmocom/gprs/rlcmac/rlcmac_dec.h 
b/include/osmocom/gprs/rlcmac/rlcmac_dec.h
index f707dcb..d07a9df 100644
--- a/include/osmocom/gprs/rlcmac/rlcmac_dec.h
+++ b/include/osmocom/gprs/rlcmac/rlcmac_dec.h
@@ -47,6 +47,13 @@
                                         struct bitvec *bits, int *bsn_begin, 
int *bsn_end,
                                         struct gprs_rlcmac_rlc_ul_window *ulw);

+#define RFN_MODULUS 42432
+
+static inline uint16_t fn2rfn(uint32_t fn)
+{
+       return fn % RFN_MODULUS;
+}
+
 uint32_t TBF_StartingTime_to_fn(const StartingTime_t *tbf_start_time, uint32_t 
curr_fn);
 uint32_t TBF_Starting_Frame_Number_to_fn(const Starting_Frame_Number_t 
*tbf_start_fn, uint32_t curr_fn);

diff --git a/src/rlcmac/rlcmac_dec.c b/src/rlcmac/rlcmac_dec.c
index d607aae..56d444c 100644
--- a/src/rlcmac/rlcmac_dec.c
+++ b/src/rlcmac/rlcmac_dec.c
@@ -429,15 +429,57 @@
        return num_blocks;
 }

+#define RFN_THRESHOLD (RFN_MODULUS / 2)
+/* Determine the full frame number from a relative frame number */
+static uint32_t rfn_to_fn(uint32_t rfn, uint32_t curr_fn)
+{
+       uint32_t curr_rfn;
+       uint32_t fn_rounded;
+
+       /* Ensure that all following calculations are performed with the
+        * relative frame number */
+       OSMO_ASSERT(rfn < RFN_MODULUS);
+
+       /* Compute an internal relative frame number from the full internal
+          frame number */
+       curr_rfn = fn2rfn(curr_fn);
+
+       /* Compute a "rounded" version of the internal frame number, which
+        * exactly fits in the RFN_MODULUS raster */
+       fn_rounded = GSM_TDMA_FN_SUB(curr_fn, curr_rfn);
+
+       /* If the delta between the internal and the external relative frame
+        * number exceeds a certain limit, we need to assume that the incoming
+        * request belongs to a the previous rfn period. To correct this,
+        * we roll back the rounded frame number by one RFN_MODULUS */
+       if (GSM_TDMA_FN_DIFF(rfn, curr_rfn) > RFN_THRESHOLD) {
+               LOGRLCMAC(LOGL_DEBUG, "Race condition between rfn (%u) and 
m_cur_fn (%u) detected: "
+                         "rfn belongs to the previous modulus %u cycle, 
wrapping...\n",
+                         rfn, curr_fn, RFN_MODULUS);
+               if (fn_rounded < RFN_MODULUS) {
+                       LOGRLCMAC(LOGL_DEBUG, "Cornercase detected: wrapping 
crosses %u border\n",
+                                 GSM_MAX_FN);
+                       fn_rounded = GSM_TDMA_FN_SUB(GSM_MAX_FN, 
(GSM_TDMA_FN_SUB(RFN_MODULUS, fn_rounded)));
+               } else {
+                       fn_rounded = GSM_TDMA_FN_SUB(fn_rounded, RFN_MODULUS);
+               }
+       }
+
+       /* The real frame number is the sum of the rounded frame number and the
+        * relative framenumber computed via RACH */
+       return GSM_TDMA_FN_SUM(fn_rounded, rfn);
+}
+
 /* 12.21 Starting Frame Number Description */
 uint32_t TBF_StartingTime_to_fn(const StartingTime_t *tbf_start_time, uint32_t 
curr_fn)
 {
-       const struct gsm_time g_time = {
-               .t1 = tbf_start_time->N32,
-               .t2 = tbf_start_time->N51,
-               .t3 = tbf_start_time->N26
-       };
-       return gsm_gsmtime2fn(&g_time);
+       const uint8_t t1 = tbf_start_time->N32;
+       const uint8_t t3 = tbf_start_time->N51;
+       const uint8_t t2 = tbf_start_time->N26;
+       const uint16_t rfn = (51 * ((t3 - t2) % 26)) + t3 + 51 * 26 * t1;
+       const uint32_t fn = rfn_to_fn(rfn, curr_fn);
+       LOGRLCMAC(LOGL_DEBUG, "curr_fn=%u + RFN=%u -> FN=%u\n", curr_fn, rfn, 
fn);
+       return fn;

 }

diff --git a/tests/rlcmac/Makefile.am b/tests/rlcmac/Makefile.am
index 9d1f5b0..c13d179 100644
--- a/tests/rlcmac/Makefile.am
+++ b/tests/rlcmac/Makefile.am
@@ -16,6 +16,7 @@
        csn1_ts_44_018_test \
        csn1_ts_44_060_test \
        rlcmac_prim_test \
+       rlcmac_types_test \
        $(NULL)

 EXTRA_DIST = \
@@ -25,6 +26,8 @@
        csn1_ts_44_060_test.err \
        rlcmac_prim_test.ok \
        rlcmac_prim_test.err \
+       rlcmac_types_test.ok \
+       rlcmac_types_test.err \
        $(NULL)

 # Common LDADD entries
@@ -44,3 +47,6 @@

 rlcmac_prim_test_SOURCES = rlcmac_prim_test.c
 rlcmac_prim_test_LDADD = $(LDADD)
+
+rlcmac_types_test_SOURCES = rlcmac_types_test.c
+rlcmac_types_test_LDADD = $(LDADD)
\ No newline at end of file
diff --git a/tests/rlcmac/rlcmac_types_test.c b/tests/rlcmac/rlcmac_types_test.c
new file mode 100644
index 0000000..18ecda9
--- /dev/null
+++ b/tests/rlcmac/rlcmac_types_test.c
@@ -0,0 +1,87 @@
+/* rlcmac_types_test.c
+ *
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/select.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm48_rest_octets.h>
+
+#include <osmocom/gprs/rlcmac/rlcmac.h>
+#include <osmocom/gprs/rlcmac/csn1_defs.h>
+#include <osmocom/gprs/rlcmac/rlcmac_dec.h>
+
+static void *tall_ctx = NULL;
+
+
+/* SGSN->PCU->BTS --PCH--> MS containing "Paging Request Type 1" asking for PS 
services.
+ * RLCMAC will send GMMRR-PAGE.ind to GMM layer, which is in charge of 
orchestrating the response. */
+static void test_tbf_starting_time_to_fn(const uint32_t cur_fn, const uint32_t 
fn)
+{
+       const uint16_t rfn = fn2rfn(fn);
+       StartingTime_t st;
+
+       printf("=== %s(cur_fn=%u, fn=%u) start ===\n", __func__, cur_fn, fn);
+
+       /* TBF_STARTING_TIME -- same as 3GPP TS 44.018 ยง10.5.2.38 Starting Time 
without tag: */
+       st.N32 = (rfn / (26 * 51)) % 32;
+       st.N51 = rfn % 51;
+       st.N26 = rfn % 26;
+
+       printf("cur_fn=%u fn=%u rfn=%u [T1'=%u T3=%u T2=%u]\n",
+              cur_fn, fn, rfn, st.N32, st.N51, st.N26);
+
+       uint32_t res_fn = TBF_StartingTime_to_fn(&st, cur_fn);
+       printf("res_fn=%u\n", res_fn);
+       OSMO_ASSERT(res_fn == fn);
+
+       printf("=== %s(cur_fn=%u, fn=%u) end ===\n", __func__, cur_fn, fn);
+}
+
+static const struct log_info_cat test_log_categories[] = { };
+static const struct log_info test_log_info = {
+       .cat = test_log_categories,
+       .num_cat = ARRAY_SIZE(test_log_categories),
+};
+
+int main(int argc, char *argv[])
+{
+       tall_ctx = talloc_named_const(NULL, 1, __FILE__);
+
+       osmo_init_logging2(tall_ctx, &test_log_info);
+       log_parse_category_mask(osmo_stderr_target, "DLGLOBAL,1:");
+       osmo_fsm_log_addr(false);
+
+       log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
+       log_set_print_category_hex(osmo_stderr_target, 0);
+       log_set_print_category(osmo_stderr_target, 1);
+       log_set_print_level(osmo_stderr_target, 1);
+       log_set_use_color(osmo_stderr_target, 0);
+
+       test_tbf_starting_time_to_fn(0, 0);
+       test_tbf_starting_time_to_fn(0, 4);
+       test_tbf_starting_time_to_fn(2229729, 2229786);
+       test_tbf_starting_time_to_fn(2229777, 2229786);
+       test_tbf_starting_time_to_fn(1320458, 1320462);
+
+       talloc_free(tall_ctx);
+}
diff --git a/tests/rlcmac/rlcmac_types_test.err 
b/tests/rlcmac/rlcmac_types_test.err
new file mode 100644
index 0000000..fd860eb
--- /dev/null
+++ b/tests/rlcmac/rlcmac_types_test.err
@@ -0,0 +1,5 @@
+DLGLOBAL DEBUG curr_fn=0 + RFN=0 -> FN=0
+DLGLOBAL DEBUG curr_fn=0 + RFN=4 -> FN=4
+DLGLOBAL DEBUG curr_fn=2229729 + RFN=23322 -> FN=2229786
+DLGLOBAL DEBUG curr_fn=2229777 + RFN=23322 -> FN=2229786
+DLGLOBAL DEBUG curr_fn=1320458 + RFN=5070 -> FN=1320462
diff --git a/tests/rlcmac/rlcmac_types_test.ok 
b/tests/rlcmac/rlcmac_types_test.ok
new file mode 100644
index 0000000..2075682
--- /dev/null
+++ b/tests/rlcmac/rlcmac_types_test.ok
@@ -0,0 +1,20 @@
+=== test_tbf_starting_time_to_fn(cur_fn=0, fn=0) start ===
+cur_fn=0 fn=0 rfn=0 [T1'=0 T3=0 T2=0]
+res_fn=0
+=== test_tbf_starting_time_to_fn(cur_fn=0, fn=0) end ===
+=== test_tbf_starting_time_to_fn(cur_fn=0, fn=4) start ===
+cur_fn=0 fn=4 rfn=4 [T1'=0 T3=4 T2=4]
+res_fn=4
+=== test_tbf_starting_time_to_fn(cur_fn=0, fn=4) end ===
+=== test_tbf_starting_time_to_fn(cur_fn=2229729, fn=2229786) start ===
+cur_fn=2229729 fn=2229786 rfn=23322 [T1'=17 T3=15 T2=0]
+res_fn=2229786
+=== test_tbf_starting_time_to_fn(cur_fn=2229729, fn=2229786) end ===
+=== test_tbf_starting_time_to_fn(cur_fn=2229777, fn=2229786) start ===
+cur_fn=2229777 fn=2229786 rfn=23322 [T1'=17 T3=15 T2=0]
+res_fn=2229786
+=== test_tbf_starting_time_to_fn(cur_fn=2229777, fn=2229786) end ===
+=== test_tbf_starting_time_to_fn(cur_fn=1320458, fn=1320462) start ===
+cur_fn=1320458 fn=1320462 rfn=5070 [T1'=3 T3=21 T2=0]
+res_fn=1320462
+=== test_tbf_starting_time_to_fn(cur_fn=1320458, fn=1320462) end ===
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 74fd43a..ce51e35 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -64,6 +64,13 @@
 AT_CHECK([$abs_top_builddir/tests/rlcmac/rlcmac_prim_test], [0], [expout], 
[experr])
 AT_CLEANUP

+AT_SETUP([rlcmac/rlcmac_types])
+AT_KEYWORDS([rlcmac rlcmac_types])
+cat $abs_srcdir/rlcmac/rlcmac_types_test.ok > expout
+cat $abs_srcdir/rlcmac/rlcmac_types_test.err > experr
+AT_CHECK([$abs_top_builddir/tests/rlcmac/rlcmac_types_test], [0], [expout], 
[experr])
+AT_CLEANUP
+
 AT_SETUP([sm/sm_prim])
 AT_KEYWORDS([sm sm_prim])
 cat $abs_srcdir/sm/sm_prim_test.ok > expout

--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/34044
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I00741289333853a8db472950ee2ac38dc2c74fd3
Gerrit-Change-Number: 34044
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-MessageType: newchange

Reply via email to