aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gsm_data.h8
-rw-r--r--openbsc/src/gsm_data.c6
-rw-r--r--openbsc/src/system_information.c115
3 files changed, 63 insertions, 66 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 9bddd7aad..52c6a030b 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -60,6 +60,7 @@ enum gsm_chreq_reason_t {
#include <openbsc/abis_rsl.h>
#include <openbsc/mncc.h>
#include <openbsc/tlv.h>
+#include <openbsc/bitvec.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -381,6 +382,13 @@ struct gsm_bts {
struct gsm48_cell_sel_par cell_sel_par;
struct gsm48_cell_options cell_options;
struct gsm48_control_channel_descr chan_desc;
+ struct bitvec neigh_list;
+ struct bitvec cell_alloc;
+ struct {
+ /* bitmask large enough for all possible ARFCN's */
+ u_int8_t neigh_list[1024/8];
+ u_int8_t cell_alloc[1024/8];
+ } data;
} si_common;
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index cdaba9e52..3cf9e3c4d 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -169,6 +169,12 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
bts->ms_max_power = 15; /* dBm */
bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
bts->si_common.cell_sel_par.rxlev_acc_min = 0;
+ bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
+ bts->si_common.neigh_list.data_len =
+ sizeof(bts->si_common.data.neigh_list);
+ bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
+ bts->si_common.cell_alloc.data_len =
+ sizeof(bts->si_common.data.cell_alloc);
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
bts->gprs.nsvc[i].bts = bts;
diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c
index 60a8219b2..2d4ba20a4 100644
--- a/openbsc/src/system_information.c
+++ b/openbsc/src/system_information.c
@@ -23,6 +23,7 @@
#include <errno.h>
#include <string.h>
+#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
@@ -30,6 +31,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/rest_octets.h>
+#include <openbsc/bitvec.h>
#define GSM48_CELL_CHAN_DESC_SIZE 16
#define GSM_MACBLOCK_LEN 23
@@ -38,7 +40,7 @@
/* Frequency Lists as per TS 04.08 10.5.2.13 */
/* 10.5.2.13.2: Bit map 0 format */
-static int cchan_list_bm0_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
+static int freq_list_bm0_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
{
unsigned int byte, bit;
@@ -57,7 +59,7 @@ static int cchan_list_bm0_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
}
/* 10.5.2.13.7: Variable bit map format */
-static int cchan_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
+static int freq_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
{
unsigned int byte, bit;
unsigned int min_arfcn;
@@ -86,20 +88,23 @@ static int cchan_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
}
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int generate_cell_chan_list(u_int8_t *chan_list, const struct gsm_bts *bts)
+static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
+ const struct gsm_bts *bts)
{
- struct gsm_bts_trx *trx;
- int rc, min = 1024, max = 0;
+ int i, rc, min = 1024, max = 0;
memset(chan_list, 0, 16);
/* GSM900-only handsets only support 'bit map 0 format' */
if (bts->band == GSM_BAND_900) {
chan_list[0] = 0;
- llist_for_each_entry(trx, &bts->trx_list, list) {
- rc = cchan_list_bm0_set_arfcn(chan_list, trx->arfcn);
- if (rc < 0)
- return rc;
+
+ for (i = 0; i < bv->data_len*8; i++) {
+ if (bitvec_get_bit_pos(bv, i)) {
+ rc = freq_list_bm0_set_arfcn(chan_list, i);
+ if (rc < 0)
+ return rc;
+ }
}
return 0;
}
@@ -107,11 +112,13 @@ static int generate_cell_chan_list(u_int8_t *chan_list, const struct gsm_bts *bt
/* We currently only support the 'Variable bitmap format' */
chan_list[0] = 0x8e;
- llist_for_each_entry(trx, &bts->trx_list, list) {
- if (trx->arfcn < min)
- min = trx->arfcn;
- if (trx->arfcn > max)
- max = trx->arfcn;
+ for (i = 0; i < bv->data_len*8; i++) {
+ if (bitvec_get_bit_pos(bv, i)) {
+ if (i < min)
+ min = i;
+ if (i > max)
+ max = i;
+ }
}
if ((max - min) > 111)
@@ -121,8 +128,8 @@ static int generate_cell_chan_list(u_int8_t *chan_list, const struct gsm_bts *bt
chan_list[1] = (min >> 1);
chan_list[2] = (min & 1) << 7;
- llist_for_each_entry(trx, &bts->trx_list, list) {
- rc = cchan_list_bmrel_set_arfcn(chan_list, trx->arfcn);
+ for (i = 0; i < bv->data_len*8; i++) {
+ rc = freq_list_bmrel_set_arfcn(chan_list, i);
if (rc < 0)
return rc;
}
@@ -131,61 +138,37 @@ static int generate_cell_chan_list(u_int8_t *chan_list, const struct gsm_bts *bt
}
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int generate_bcch_chan_list(u_int8_t *chan_list, const struct gsm_bts *bts)
+static int generate_cell_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
{
- struct gsm_bts *cur_bts;
struct gsm_bts_trx *trx;
- int rc, min = 1024, max = 0;
-
- memset(chan_list, 0, 16);
-
- /* GSM900-only handsets only support 'bit map 0 format' */
- if (bts->band == GSM_BAND_900) {
- chan_list[0] = 0;
- llist_for_each_entry(cur_bts, &bts->list, list) {
- if (&cur_bts->list == &bts->network->bts_list)
- continue;
- trx = cur_bts->c0;
- rc = cchan_list_bm0_set_arfcn(chan_list, trx->arfcn);
- if (rc < 0)
- return rc;
- }
- return 0;
- }
-
- /* We currently only support the 'Variable bitmap format' */
- chan_list[0] = 0x8e;
+ struct bitvec *bv = &bts->si_common.cell_alloc;
- llist_for_each_entry(cur_bts, &bts->list, list) {
- if (&cur_bts->list == &bts->network->bts_list)
- continue;
- trx = cur_bts->c0;
- if (trx->arfcn < min)
- min = trx->arfcn;
- if (trx->arfcn > max)
- max = trx->arfcn;
- }
+ /* first we generate a bitvec of all TRX ARFCN's in our BTS */
+ llist_for_each_entry(trx, &bts->trx_list, list)
+ bitvec_set_bit_pos(bv, trx->arfcn, 1);
- if ((max - min) > 111)
- return -EINVAL;
+ /* then we generate a GSM 04.08 frequency list from the bitvec */
+ return bitvec2freq_list(chan_list, bv, bts);
+}
- chan_list[0] |= (min >> 9) & 1;
- chan_list[1] = (min >> 1);
- chan_list[2] = (min & 1) << 7;
+/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
+static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
+{
+ struct gsm_bts *cur_bts;
+ struct bitvec *bv = &bts->si_common.neigh_list;
- llist_for_each_entry(cur_bts, &bts->list, list) {
- if (&cur_bts->list == &bts->network->bts_list)
+ /* first we generate a bitvec of the BCCH ARFCN's in our BSC */
+ llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
+ if (cur_bts == bts)
continue;
- trx = cur_bts->c0;
- rc = cchan_list_bmrel_set_arfcn(chan_list, trx->arfcn);
- if (rc < 0)
- return rc;
+ bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
}
- return 0;
+ /* then we generate a GSM 04.08 frequency list from the bitvec */
+ return bitvec2freq_list(chan_list, bv, bts);
}
-static int generate_si1(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si1(u_int8_t *output, struct gsm_bts *bts)
{
int rc;
struct gsm48_system_information_type_1 *si1 =
@@ -210,7 +193,7 @@ static int generate_si1(u_int8_t *output, const struct gsm_bts *bts)
return GSM_MACBLOCK_LEN;
}
-static int generate_si2(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si2(u_int8_t *output, struct gsm_bts *bts)
{
int rc;
struct gsm48_system_information_type_2 *si2 =
@@ -257,7 +240,7 @@ struct gsm48_si_ro_info si_info = {
.break_ind = 0,
};
-static int generate_si3(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
{
struct gsm48_system_information_type_3 *si3 =
(struct gsm48_system_information_type_3 *) output;
@@ -287,7 +270,7 @@ static int generate_si3(u_int8_t *output, const struct gsm_bts *bts)
return GSM_MACBLOCK_LEN;
}
-static int generate_si4(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
{
struct gsm48_system_information_type_4 *si4 =
(struct gsm48_system_information_type_4 *) output;
@@ -319,7 +302,7 @@ static int generate_si4(u_int8_t *output, const struct gsm_bts *bts)
return GSM_MACBLOCK_LEN;
}
-static int generate_si5(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si5(u_int8_t *output, struct gsm_bts *bts)
{
struct gsm48_system_information_type_5 *si5 =
(struct gsm48_system_information_type_5 *) output;
@@ -339,7 +322,7 @@ static int generate_si5(u_int8_t *output, const struct gsm_bts *bts)
return 18;
}
-static int generate_si6(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si6(u_int8_t *output, struct gsm_bts *bts)
{
struct gsm48_system_information_type_6 *si6 =
(struct gsm48_system_information_type_6 *) output;
@@ -390,7 +373,7 @@ static struct gsm48_si13_info si13_default = {
},
};
-static int generate_si13(u_int8_t *output, const struct gsm_bts *bts)
+static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
{
struct gsm48_system_information_type_13 *si13 =
(struct gsm48_system_information_type_13 *) output;