aboutsummaryrefslogtreecommitdiffstats
path: root/src/bts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bts.cpp')
-rw-r--r--src/bts.cpp71
1 files changed, 57 insertions, 14 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 21e9d968..548d0009 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -34,6 +34,7 @@ extern "C" {
#include <osmocom/core/msgb.h>
#include <osmocom/core/stats.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
+ #include <osmocom/gsm/gsm_utils.h>
}
#include <arpa/inet.h>
@@ -41,6 +42,9 @@ extern "C" {
#include <errno.h>
#include <string.h>
+#define RFN_MODULUS 42432
+#define RFN_THRESHOLD RFN_MODULUS / 2
+
extern void *tall_pcu_ctx;
static BTS s_bts;
@@ -516,6 +520,57 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
return 0;
}
+/* Determine the full frame number from a relative frame number */
+uint32_t BTS::rfn_to_fn(uint32_t rfn)
+{
+ uint32_t m_cur_rfn;
+ uint32_t fn;
+ uint32_t fn_rounded;
+
+ /* Note: If a BTS is sending in a rach request it will be fully aware
+ * of the frame number. If the PCU is used in a BSC-co-located setup.
+ * The BSC will forward the incoming RACH request. The RACH request
+ * only contains the relative frame number (Fn % 42432) in its request
+ * reference. This PCU implementation has to fit both scenarios, so
+ * we need to assume that Fn is a relative frame number. */
+
+ /* Ensure that all following calculations are performed with the
+ * relative frame number */
+ rfn = rfn % 42432;
+
+ /* Compute an internal relative frame number from the full internal
+ frame number */
+ m_cur_rfn = m_cur_fn % RFN_MODULUS;
+
+ /* Compute a "rounded" version of the internal frame number, which
+ * exactly fits in the RFN_MODULUS raster */
+ fn_rounded = m_cur_fn - m_cur_rfn;
+
+ /* If the delta between the internal and the external relative frame
+ * number exceeds a certain limit, we need to assume that the incoming
+ * rach request belongs to a the previous rfn period. To correct this,
+ * we roll back the rounded frame number by one RFN_MODULUS */
+ if (abs(rfn - m_cur_rfn) > RFN_THRESHOLD) {
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Race condition between rfn (%u) and m_cur_fn (%u) detected: rfn belongs to the previos modulus %u cycle, wrappng...\n",
+ rfn, m_cur_fn, RFN_MODULUS);
+ if (fn_rounded < RFN_MODULUS) {
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Cornercase detected: wrapping crosses %u border\n",
+ GSM_MAX_FN);
+ fn_rounded = GSM_MAX_FN - (RFN_MODULUS - fn_rounded);
+ }
+ else
+ fn_rounded -= RFN_MODULUS;
+ }
+
+ /* The real frame number is the sum of the rounded frame number and the
+ * relative framenumber computed via RACH */
+ fn = fn_rounded + rfn;
+
+ return fn;
+}
+
int BTS::rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, uint8_t is_11bit,
enum ph_burst_type burst_type)
{
@@ -536,20 +591,8 @@ int BTS::rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, uint8_t is_11bit,
if (is_11bit)
rach_frame_11bit();
- /* Note: If a BTS is sending in a rach request it will be fully aware
- * of the frame number. If the PCU is used in a BSC-co-located setup.
- * The BSC will forward the incoming RACH request. The RACH request
- * only contains the relative frame number (Fn % 42432) in its request
- * reference. This PCU implementation has to fit both secenarious, so
- * we need to assume that Fn is a relative frame number. */
-
- /* Ensure that all following calculations are performed with the
- * relative frame number */
- Fn = Fn % 42432;
-
- /* Restore the full frame number
- * (See also 3GPP TS 44.018, section 10.5.2.38) */
- Fn = Fn + m_cur_fn - m_cur_fn % 42432;
+ /* Determine full frame number */
+ Fn = rfn_to_fn(Fn);
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, "
"so we provide one: ra=0x%02x Fn=%u qta=%d is_11bit=%d:\n",