summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2017-04-12 15:30:54 +0200
committerMax <msuraev@sysmocom.de>2017-04-28 08:45:36 +0000
commit6f0e50c8337355eb59033903ede9ab6528890835 (patch)
treed272206d3708f575ed73d5d8e96ea359d3d5310b
parenta18001d50605b0c7d4ae54c812b8766f8e7f5f61 (diff)
Prepare for extended SI2quater support
Supporting SI2quater as per 3GPP TS 44.018 will require chnages to the way System Information is stored because it uses 1:n instead of 1:1 mapping between SI type and generated SI content. This should not affect other SI types though. To facilitate this transition: * convert the code to always use GSM_BTS_SI helper instead of accessing buffer directly * make helper more robust by adding extra parenthesis * add similar helper for gsm_lchan * add function estimating number of SI2quater message to hold configured number of (U|E)ARFCNs * add SI2q index/count fields and pass them to rest_octets generator explicitly * internalize buffer access in generate_si* functions Change-Id: I74e4e3cb86364cec869a1472a41b4a95af0d50dd Related: RT#8792
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h6
-rw-r--r--openbsc/include/openbsc/rest_octets.h5
-rw-r--r--openbsc/include/openbsc/system_information.h2
-rw-r--r--openbsc/src/libbsc/bsc_vty.c10
-rw-r--r--openbsc/src/libbsc/rest_octets.c6
-rw-r--r--openbsc/src/libbsc/system_information.c87
-rw-r--r--openbsc/tests/gsm0408/gsm0408_test.c5
7 files changed, 60 insertions, 61 deletions
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 242889a45..166de1610 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -483,7 +483,8 @@ struct gsm_bts_trx {
struct gsm_bts_trx_ts ts[TRX_NR_TS];
};
-#define GSM_BTS_SI(bts, i) (void *)(bts->si_buf[i])
+#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i])
+#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i])
enum gsm_bts_type {
GSM_BTS_TYPE_UNKNOWN,
@@ -702,6 +703,9 @@ struct gsm_bts {
/* bitmask of all SI that are present/valid in si_buf */
uint32_t si_valid;
+ /* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
+ uint8_t si2q_index;
+ uint8_t si2q_count;
/* buffers where we put the pre-computed SI */
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h
index 3b4e598bf..73ce57b26 100644
--- a/openbsc/include/openbsc/rest_octets.h
+++ b/openbsc/include/openbsc/rest_octets.h
@@ -5,12 +5,15 @@
#include <openbsc/gsm_04_08.h>
#include <osmocom/gsm/sysinfo.h>
+/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018: 4-bit index is used */
+#define SI2Q_MAX_NUM 16
+/* length in bits (for single SI2quater message) */
#define SI2Q_MAX_LEN 160
#define SI2Q_MIN_LEN 18
/* generate SI1 rest octets */
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);
-int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
+int rest_octets_si2quater(uint8_t *data, uint8_t index, uint8_t count, const struct osmo_earfcn_si2q *e,
const uint16_t *u, const uint16_t *sc, size_t u_len);
int rest_octets_si6(uint8_t *data, bool is1800_net);
diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h
index 1b19c8bc5..b012107b5 100644
--- a/openbsc/include/openbsc/system_information.h
+++ b/openbsc/include/openbsc/system_information.h
@@ -14,7 +14,7 @@ unsigned range1024_p(unsigned n);
unsigned range512_q(unsigned m);
int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w,
int f0, uint8_t *chan_list);
-bool si2q_size_check(const struct gsm_bts *bts);
+uint8_t si2q_num(const struct gsm_bts *bts);
int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble);
int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
bool diversity);
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 3c70580ac..195fd6a96 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -644,7 +644,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
get_value_string(osmo_sitype_strs, i), VTY_NEWLINE);
vty_out(vty, " system-information %s static %s%s",
get_value_string(osmo_sitype_strs, i),
- osmo_hexdump_nospc(bts->si_buf[i], sizeof(bts->si_buf[i])),
+ osmo_hexdump_nospc(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN),
VTY_NEWLINE);
}
}
@@ -2687,11 +2687,11 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
}
/* Fill buffer with padding pattern */
- memset(bts->si_buf[type], 0x2b, sizeof(bts->si_buf[type]));
+ memset(GSM_BTS_SI(bts, type), 0x2b, GSM_MACBLOCK_LEN);
/* Parse the user-specified SI in hex format, [partially] overwriting padding */
- rc = osmo_hexparse(argv[1], bts->si_buf[type], sizeof(bts->si_buf[0]));
- if (rc < 0 || rc > sizeof(bts->si_buf[0])) {
+ rc = osmo_hexparse(argv[1], GSM_BTS_SI(bts, type), GSM_MACBLOCK_LEN);
+ if (rc < 0 || rc > GSM_MACBLOCK_LEN) {
vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -2829,7 +2829,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd,
e->prio_valid = true;
}
- if (si2q_size_check(bts))
+ if (si2q_num(bts) < 2)
return CMD_SUCCESS;
vty_out(vty, "Warning: not enough space in SI2quater for a given EARFCN "
diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c
index ed6c573d5..af660f1f1 100644
--- a/openbsc/src/libbsc/rest_octets.c
+++ b/openbsc/src/libbsc/rest_octets.c
@@ -256,7 +256,7 @@ static inline int append_uarfcns(struct bitvec *bv, const uint16_t *u,
}
/* generate SI2quater rest octets: 3GPP TS 44.018 ยง 10.5.2.33b */
-int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
+int rest_octets_si2quater(uint8_t *data, uint8_t index, uint8_t count, const struct osmo_earfcn_si2q *e,
const uint16_t *u, const uint16_t *sc, size_t u_len)
{
int rc;
@@ -275,9 +275,9 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
/* we do not support multiple si2quater messages at the moment: */
/* SI2quater_INDEX */
- bitvec_set_uint(&bv, 0, 4);
+ bitvec_set_uint(&bv, index, 4);
/* SI2quater_COUNT */
- bitvec_set_uint(&bv, 0, 4);
+ bitvec_set_uint(&bv, count, 4);
/* No Measurement_Parameters Description */
bitvec_set_bit(&bv, 0);
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c
index 261033147..37395f00f 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -149,18 +149,13 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len)
return s + r + append + range1024_p(k);
}
-bool si2q_size_check(const struct gsm_bts *bts)
+uint8_t si2q_num(const struct gsm_bts *bts)
{
- const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
- const uint16_t *u = bts->si_common.data.uarfcn_list,
- *sc = bts->si_common.data.scramble_list;
- size_t len = bts->si_common.uarfcn_length;
- unsigned e_sz = e ? earfcn_size(e) : 1,
- u_sz = len ? uarfcn_size(u, sc, len) : 1;
+ const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; /* EARFCN */
+ const uint16_t *u = bts->si_common.data.uarfcn_list, *sc = bts->si_common.data.scramble_list; /* UARFCN */
+ size_t l = bts->si_common.uarfcn_length, e_sz = e ? earfcn_size(e) : 1, u_sz = l ? uarfcn_size(u, sc, l) : 1;
/* 2 bits are used in between UARFCN and EARFCN structs */
- if (SI2Q_MIN_LEN + u_sz + 2 + e_sz > SI2Q_MAX_LEN)
- return false;
- return true;
+ return 1 + (e_sz + u_sz) / (SI2Q_MAX_LEN - (SI2Q_MIN_LEN + 2));
}
/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */
@@ -233,7 +228,7 @@ int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
scl[k] = scr;
bts->si_common.uarfcn_length++;
- if (si2q_size_check(bts))
+ if (si2q_num(bts) < 2)
return 0;
bts_uarfcn_del(bts, arfcn, scramble);
@@ -557,11 +552,10 @@ static int list_arfcn(uint8_t *chan_list, uint8_t mask, char *text)
return n;
}
-static int generate_si1(uint8_t *output, struct gsm_bts *bts)
+static int generate_si1(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
- struct gsm48_system_information_type_1 *si1 =
- (struct gsm48_system_information_type_1 *) output;
+ struct gsm48_system_information_type_1 *si1 = (struct gsm48_system_information_type_1 *) GSM_BTS_SI(bts, t);
memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -586,11 +580,10 @@ static int generate_si1(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si1) + rc;
}
-static int generate_si2(uint8_t *output, struct gsm_bts *bts)
+static int generate_si2(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
- struct gsm48_system_information_type_2 *si2 =
- (struct gsm48_system_information_type_2 *) output;
+ struct gsm48_system_information_type_2 *si2 = (struct gsm48_system_information_type_2 *) GSM_BTS_SI(bts, t);
memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -611,11 +604,11 @@ static int generate_si2(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si2);
}
-static int generate_si2bis(uint8_t *output, struct gsm_bts *bts)
+static int generate_si2bis(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
struct gsm48_system_information_type_2bis *si2b =
- (struct gsm48_system_information_type_2bis *) output;
+ (struct gsm48_system_information_type_2bis *) GSM_BTS_SI(bts, t);
int n;
memset(si2b, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -633,8 +626,7 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts)
if (n) {
/* indicate in SI2 and SI2bis: there is an extension */
struct gsm48_system_information_type_2 *si2 =
- (struct gsm48_system_information_type_2 *)
- bts->si_buf[SYSINFO_TYPE_2];
+ (struct gsm48_system_information_type_2 *) GSM_BTS_SI(bts, SYSINFO_TYPE_2);
si2->bcch_frequency_list[0] |= 0x20;
si2b->bcch_frequency_list[0] |= 0x20;
} else
@@ -645,11 +637,11 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si2b);
}
-static int generate_si2ter(uint8_t *output, struct gsm_bts *bts)
+static int generate_si2ter(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
struct gsm48_system_information_type_2ter *si2t =
- (struct gsm48_system_information_type_2ter *) output;
+ (struct gsm48_system_information_type_2ter *) GSM_BTS_SI(bts, t);
int n;
memset(si2t, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -670,11 +662,11 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si2t);
}
-static int generate_si2quater(uint8_t *output, struct gsm_bts *bts)
+static int generate_si2quater(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc, i = MAX_EARFCN_LIST;
struct gsm48_system_information_type_2quater *si2q =
- (struct gsm48_system_information_type_2quater *) output;
+ (struct gsm48_system_information_type_2quater *) GSM_BTS_SI(bts, t);
memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -683,7 +675,7 @@ static int generate_si2quater(uint8_t *output, struct gsm_bts *bts)
si2q->header.skip_indicator = 0;
si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater;
- rc = rest_octets_si2quater(si2q->rest_octets,
+ rc = rest_octets_si2quater(si2q->rest_octets, bts->si2q_index, bts->si2q_count,
&bts->si_common.si2quater_neigh_list,
bts->si_common.data.uarfcn_list,
bts->si_common.data.scramble_list,
@@ -727,11 +719,10 @@ static struct gsm48_si_ro_info si_info = {
.break_ind = 0,
};
-static int generate_si3(uint8_t *output, struct gsm_bts *bts)
+static int generate_si3(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
- struct gsm48_system_information_type_3 *si3 =
- (struct gsm48_system_information_type_3 *) output;
+ struct gsm48_system_information_type_3 *si3 = (struct gsm48_system_information_type_3 *) GSM_BTS_SI(bts, t);
memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -775,11 +766,10 @@ static int generate_si3(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si3) + rc;
}
-static int generate_si4(uint8_t *output, struct gsm_bts *bts)
+static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
int rc;
- struct gsm48_system_information_type_4 *si4 =
- (struct gsm48_system_information_type_4 *) output;
+ struct gsm48_system_information_type_4 *si4 = (struct gsm48_system_information_type_4 *) GSM_BTS_SI(bts, t);
struct gsm_lchan *cbch_lchan;
uint8_t *restoct = si4->data;
@@ -815,14 +805,15 @@ static int generate_si4(uint8_t *output, struct gsm_bts *bts)
/* SI4 Rest Octets (10.5.2.35), containing
Optional Power offset, GPRS Indicator,
Cell Identity, LSA ID, Selection Parameter */
- rc = rest_octets_si4(restoct, &si_info, output + GSM_MACBLOCK_LEN - restoct);
+ rc = rest_octets_si4(restoct, &si_info, (uint8_t *)GSM_BTS_SI(bts, t) + GSM_MACBLOCK_LEN - restoct);
return l2_plen + 1 + rc;
}
-static int generate_si5(uint8_t *output, struct gsm_bts *bts)
+static int generate_si5(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
struct gsm48_system_information_type_5 *si5;
+ uint8_t *output = GSM_BTS_SI(bts, t);
int rc, l2_plen = 18;
memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -838,7 +829,7 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts)
break;
}
- si5 = (struct gsm48_system_information_type_5 *) output;
+ si5 = (struct gsm48_system_information_type_5 *) GSM_BTS_SI(bts, t);
/* l2 pseudo length, not part of msg: 18 */
si5->rr_protocol_discriminator = GSM48_PDISC_RR;
@@ -854,9 +845,10 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts)
return l2_plen;
}
-static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
+static int generate_si5bis(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
struct gsm48_system_information_type_5bis *si5b;
+ uint8_t *output = GSM_BTS_SI(bts, t);
int rc, l2_plen = 18;
int n;
@@ -873,7 +865,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
break;
}
- si5b = (struct gsm48_system_information_type_5bis *) output;
+ si5b = (struct gsm48_system_information_type_5bis *) GSM_BTS_SI(bts, t);
/* l2 pseudo length, not part of msg: 18 */
si5b->rr_protocol_discriminator = GSM48_PDISC_RR;
@@ -887,8 +879,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
if (n) {
/* indicate in SI5 and SI5bis: there is an extension */
struct gsm48_system_information_type_5 *si5 =
- (struct gsm48_system_information_type_5 *)
- bts->si_buf[SYSINFO_TYPE_5];
+ (struct gsm48_system_information_type_5 *) GSM_BTS_SI(bts, SYSINFO_TYPE_5);
si5->bcch_frequency_list[0] |= 0x20;
si5b->bcch_frequency_list[0] |= 0x20;
} else
@@ -898,9 +889,10 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
return l2_plen;
}
-static int generate_si5ter(uint8_t *output, struct gsm_bts *bts)
+static int generate_si5ter(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
struct gsm48_system_information_type_5ter *si5t;
+ uint8_t *output = GSM_BTS_SI(bts, t);
int rc, l2_plen = 18;
int n;
@@ -917,7 +909,7 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts)
break;
}
- si5t = (struct gsm48_system_information_type_5ter *) output;
+ si5t = (struct gsm48_system_information_type_5ter *) GSM_BTS_SI(bts, t);
/* l2 pseudo length, not part of msg: 18 */
si5t->rr_protocol_discriminator = GSM48_PDISC_RR;
@@ -935,9 +927,10 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts)
return l2_plen;
}
-static int generate_si6(uint8_t *output, struct gsm_bts *bts)
+static int generate_si6(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
struct gsm48_system_information_type_6 *si6;
+ uint8_t *output = GSM_BTS_SI(bts, t);
int l2_plen = 11;
int rc;
@@ -954,7 +947,7 @@ static int generate_si6(uint8_t *output, struct gsm_bts *bts)
break;
}
- si6 = (struct gsm48_system_information_type_6 *) output;
+ si6 = (struct gsm48_system_information_type_6 *) GSM_BTS_SI(bts, t);
/* l2 pseudo length, not part of msg: 11 */
si6->rr_protocol_discriminator = GSM48_PDISC_RR;
@@ -1015,10 +1008,10 @@ static struct gsm48_si13_info si13_default = {
},
};
-static int generate_si13(uint8_t *output, struct gsm_bts *bts)
+static int generate_si13(enum osmo_sysinfo_type t, struct gsm_bts *bts)
{
struct gsm48_system_information_type_13 *si13 =
- (struct gsm48_system_information_type_13 *) output;
+ (struct gsm48_system_information_type_13 *) GSM_BTS_SI(bts, t);
int ret;
memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
@@ -1048,7 +1041,7 @@ static int generate_si13(uint8_t *output, struct gsm_bts *bts)
return sizeof (*si13) + ret;
}
-typedef int (*gen_si_fn_t)(uint8_t *output, struct gsm_bts *bts);
+typedef int (*gen_si_fn_t)(enum osmo_sysinfo_type t, struct gsm_bts *bts);
static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = {
[SYSINFO_TYPE_1] = &generate_si1,
@@ -1090,5 +1083,5 @@ int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type)
if (!gen_si)
return -EINVAL;
- return gen_si(bts->si_buf[si_type], bts);
+ return gen_si(si_type, bts);
}
diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c
index 08cf43f50..81dc177d7 100644
--- a/openbsc/tests/gsm0408/gsm0408_test.c
+++ b/openbsc/tests/gsm0408/gsm0408_test.c
@@ -99,13 +99,12 @@ static inline void gen(struct gsm_bts *bts)
bts->si_valid = 0;
bts->si_valid |= (1 << SYSINFO_TYPE_2quater);
/* should be no-op as entire buffer is filled with padding: */
- memset(bts->si_buf[SYSINFO_TYPE_2quater], 0xAE, GSM_MACBLOCK_LEN);
+ memset(GSM_BTS_SI(bts, SYSINFO_TYPE_2quater), 0xAE, GSM_MACBLOCK_LEN);
int r = gsm_generate_si(bts, SYSINFO_TYPE_2quater);
bool v = bts->si_valid & (1 << SYSINFO_TYPE_2quater);
if (r > 0)
printf("generated %s SI2quater: [%d] %s\n",
- v ? "valid" : "invalid", r,
- osmo_hexdump(bts->si_buf[SYSINFO_TYPE_2quater], r));
+ v ? "valid" : "invalid", r, osmo_hexdump(GSM_BTS_SI(bts, SYSINFO_TYPE_2quater), r));
else
printf("failed to generate SI2quater: %s\n", strerror(-r));
}