mirror of https://gerrit.osmocom.org/libosmocore
gsm: Introduce functions to convert between FN and RFN (Reduced FN)
Implementation ported from osmo-pcu.git e98b315d12fb009359410809f4169f9380f3d933, function bts_rfn_to_fn(). This functionality can be used by osmo-pcu, libosmo-gprs or any other related code which needs to handle RFNs. Change-Id: Ib71e8da976f6cc84c3a4ab17b0a8c2101492e243
This commit is contained in:
parent
1247aa1fc0
commit
aea78a2483
|
@ -188,6 +188,14 @@ char *osmo_dump_gsmtime(const struct gsm_time *tm);
|
|||
char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm);
|
||||
char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm);
|
||||
|
||||
/* Reduced Frame Number (3GPP TS 44.018 §10.5.2.38) */
|
||||
#define GSM_RFN_MODULUS 42432
|
||||
uint32_t gsm_rfn2fn(uint16_t rfn, uint32_t curr_fn);
|
||||
static inline uint16_t gsm_fn2rfn(uint32_t fn)
|
||||
{
|
||||
return fn % GSM_RFN_MODULUS;
|
||||
}
|
||||
|
||||
/* GSM TS 03.03 Chapter 2.6 */
|
||||
enum gprs_tlli_type {
|
||||
TLLI_LOCAL,
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/meas_rep.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/gsm0502.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -924,6 +925,45 @@ char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm)
|
|||
return osmo_dump_gsmtime_buf(buf, 64, tm);
|
||||
}
|
||||
|
||||
#define GSM_RFN_THRESHOLD (GSM_RFN_MODULUS / 2)
|
||||
uint32_t gsm_rfn2fn(uint16_t rfn, uint32_t curr_fn)
|
||||
{
|
||||
uint32_t curr_rfn;
|
||||
uint32_t fn_rounded;
|
||||
const uint32_t rfn32 = rfn; /* used as 32bit for calculations */
|
||||
|
||||
/* Ensure that all following calculations are performed with the
|
||||
* relative frame number */
|
||||
OSMO_ASSERT(rfn32 < GSM_RFN_MODULUS);
|
||||
|
||||
/* Compute an internal relative frame number from the full internal
|
||||
frame number */
|
||||
curr_rfn = gsm_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(rfn32, curr_rfn) > GSM_RFN_THRESHOLD) {
|
||||
/* Race condition between rfn and curr_fn detected: rfn belongs
|
||||
to the previous RFN_MODULUS cycle, wrapping... */
|
||||
if (fn_rounded < GSM_RFN_MODULUS) {
|
||||
/* Corner case detected: wrapping crosses GSM_MAX_FN border */
|
||||
fn_rounded = GSM_TDMA_FN_SUB(GSM_MAX_FN, (GSM_TDMA_FN_SUB(GSM_RFN_MODULUS, fn_rounded)));
|
||||
} else {
|
||||
fn_rounded = GSM_TDMA_FN_SUB(fn_rounded, GSM_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, rfn32);
|
||||
}
|
||||
|
||||
/*! append range1024 encoded data to bit vector
|
||||
* \param[out] bv Caller-provided output bit-vector
|
||||
* \param[in] r Input Range1024 sructure */
|
||||
|
|
|
@ -544,6 +544,7 @@ gsm_gsmtime2fn;
|
|||
osmo_dump_gsmtime;
|
||||
osmo_dump_gsmtime_buf;
|
||||
osmo_dump_gsmtime_c;
|
||||
gsm_rfn2fn;
|
||||
|
||||
gsm_milenage;
|
||||
gsm_septet_encode;
|
||||
|
|
|
@ -1946,6 +1946,31 @@ static void test_gsm_gsmtime2fn(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_gsm_rfn2fn(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct {
|
||||
uint32_t curr_fn;
|
||||
uint16_t rfn;
|
||||
uint32_t exp_fn;
|
||||
} input[] = {
|
||||
{ .curr_fn = 0, .rfn = 0, .exp_fn = 0 },
|
||||
{ .curr_fn = 0, .rfn = 4, .exp_fn = 4 },
|
||||
{ .curr_fn = 2229729, .rfn = 23322, .exp_fn = 2229786 },
|
||||
{ .curr_fn = 2229777, .rfn = 23322, .exp_fn = 2229786 },
|
||||
{ .curr_fn = 1320458, .rfn = 5070, .exp_fn = 1320462 },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(input); i++) {
|
||||
uint32_t fn = gsm_rfn2fn(input[i].rfn, input[i].curr_fn);
|
||||
if (fn != input[i].exp_fn) {
|
||||
printf("Wrong frame number computed! curr_fn=%u, rfn=%u ==> fn=%u, expected fn=%u\n",
|
||||
input[i].curr_fn, input[i].rfn, fn, input[i].exp_fn);
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_bearer_cap();
|
||||
|
@ -1967,6 +1992,7 @@ int main(int argc, char **argv)
|
|||
test_power_ctrl();
|
||||
test_rach_tx_integer_raw2val();
|
||||
test_gsm_gsmtime2fn();
|
||||
test_gsm_rfn2fn();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue