aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/bsc/bts.h1
-rw-r--r--include/osmocom/bsc/system_information.h1
-rw-r--r--src/osmo-bsc/bsc_vty.c27
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c39
-rw-r--r--src/osmo-bsc/system_information.c61
5 files changed, 93 insertions, 36 deletions
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index c8cf8b330..c03c75ed6 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -451,6 +451,7 @@ struct gsm_bts {
struct bitvec si5_neigh_list;
struct osmo_earfcn_si2q si2quater_neigh_list;
size_t uarfcn_length; /* index for uarfcn and scramble lists */
+ size_t cell_chan_num; /* number of channels in Cell Allocation */
struct {
/* bitmask large enough for all possible ARFCN's */
uint8_t neigh_list[1024/8];
diff --git a/include/osmocom/bsc/system_information.h b/include/osmocom/bsc/system_information.h
index 35892d9d6..e86a3493c 100644
--- a/include/osmocom/bsc/system_information.h
+++ b/include/osmocom/bsc/system_information.h
@@ -7,6 +7,7 @@
struct gsm_bts;
+int generate_cell_chan_alloc(struct gsm_bts *bts);
int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts);
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e);
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 6a6411f1a..5eb23936d 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -5334,6 +5334,12 @@ DEFUN_USRATTR(cfg_trx_arfcn,
trx->arfcn = arfcn;
+ /* Update Cell Allocation (list of all the frequencies allocated to a cell) */
+ if (generate_cell_chan_alloc(trx->bts) != 0) {
+ vty_out(vty, "%% Failed to re-generate Cell Allocation%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
/* FIXME: patch ARFCN into SYSTEM INFORMATION */
/* FIXME: use OML layer to update the ARFCN */
/* FIXME: use RSL layer to update SYSTEM INFORMATION */
@@ -5604,6 +5610,13 @@ DEFUN_USRATTR(cfg_ts_arfcn_add,
bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 1);
+ /* Update Cell Allocation (list of all the frequencies allocated to a cell) */
+ if (generate_cell_chan_alloc(ts->trx->bts) != 0) {
+ vty_out(vty, "%% Failed to re-generate Cell Allocation%s", VTY_NEWLINE);
+ bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, ZERO); /* roll-back */
+ return CMD_WARNING;
+ }
+
return CMD_SUCCESS;
}
@@ -5630,6 +5643,13 @@ DEFUN_USRATTR(cfg_ts_arfcn_del,
bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 0);
+ /* Update Cell Allocation (list of all the frequencies allocated to a cell) */
+ if (generate_cell_chan_alloc(ts->trx->bts) != 0) {
+ vty_out(vty, "%% Failed to re-generate Cell Allocation%s", VTY_NEWLINE);
+ /* It's unlikely to happen on removal, so we don't roll-back */
+ return CMD_WARNING;
+ }
+
return CMD_SUCCESS;
}
@@ -5644,6 +5664,13 @@ DEFUN_USRATTR(cfg_ts_arfcn_del_all,
bitvec_zero(&ts->hopping.arfcns);
+ /* Update Cell Allocation (list of all the frequencies allocated to a cell) */
+ if (generate_cell_chan_alloc(ts->trx->bts) != 0) {
+ vty_out(vty, "%% Failed to re-generate Cell Allocation%s", VTY_NEWLINE);
+ /* It's unlikely to happen on removal, so we don't roll-back */
+ return CMD_WARNING;
+ }
+
return CMD_SUCCESS;
}
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 6c7c2753a..2b4224fd6 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -260,10 +260,10 @@ static void generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
{
/* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs
* and the MA */
+ const size_t num_cell_arfcns = ts->trx->bts->si_common.cell_chan_num;
const struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc;
const struct bitvec *ts_arfcn = &ts->hopping.arfcns;
struct bitvec *ma = &ts->hopping.ma;
- unsigned int num_cell_arfcns;
int i;
/* re-set the MA to all-zero */
@@ -273,13 +273,6 @@ static void generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
if (!ts->hopping.enabled)
return;
- /* count the number of ARFCNs in the cell channel allocation */
- num_cell_arfcns = 0;
- for (i = 0; i < 1024; i++) {
- if (bitvec_get_bit_pos(cell_chan, i))
- num_cell_arfcns++;
- }
-
/* pad it to octet-aligned number of bits */
ts->hopping.ma_len = OSMO_BYTES_FOR_BITS(num_cell_arfcns);
ma->cur_bit = (ts->hopping.ma_len * 8) - 1;
@@ -305,6 +298,20 @@ static void generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
}
}
+static void generate_ma_for_bts(struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx;
+ unsigned int tn;
+
+ OSMO_ASSERT(bts->si_common.cell_chan_num > 0);
+ OSMO_ASSERT(bts->si_common.cell_chan_num <= 64);
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
+ generate_ma_for_ts(&trx->ts[tn]);
+ }
+}
+
static void bootstrap_rsl(struct gsm_bts_trx *trx)
{
unsigned int i;
@@ -388,19 +395,9 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_L_INP_TEI_UP:
if (isd->link_type == E1INP_SIGN_OML) {
- /* TODO: this is required for the Nokia BTS, hopping is configured
- during OML, other MA is not set. */
- struct gsm_bts_trx *cur_trx;
- uint8_t ca[20];
- /* has to be called before generate_ma_for_ts to
- set bts->si_common.cell_alloc */
- generate_cell_chan_list(ca, trx->bts);
-
- llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
- int i;
- for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
- generate_ma_for_ts(&cur_trx->ts[i]);
- }
+ /* Generate Mobile Allocation bit-masks for all timeslots.
+ * This needs to be done here, because it's used for TS configuration. */
+ generate_ma_for_bts(trx->bts);
}
if (isd->link_type == E1INP_SIGN_RSL)
bootstrap_rsl(trx);
diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c
index e2ac04d4e..0dbf53c19 100644
--- a/src/osmo-bsc/system_information.c
+++ b/src/osmo-bsc/system_information.c
@@ -574,31 +574,62 @@ static int bitvec2freq_list(uint8_t *chan_list, const struct bitvec *bv,
return -EINVAL;
}
-/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
+/* (Re)generate Cell Allocation (basically a bit-vector of all cell channels) */
+int generate_cell_chan_alloc(struct gsm_bts *bts)
{
- struct bitvec *bv = &bts->si_common.cell_alloc;
const struct gsm_bts_trx *trx;
+ unsigned int chan, chan_num;
+ unsigned int tn;
+
+ /* Temporary Cell Allocation bit-vector */
+ uint8_t ca[1024 / 8] = { 0 };
+ struct bitvec bv = {
+ .data_len = sizeof(ca),
+ .data = &ca[0],
+ };
- /* Zero-initialize the bit-vector */
- memset(bv->data, 0, bv->data_len);
-
- /* first we generate a bitvec of all TRX ARFCN's in our BTS */
+ /* Calculate a bit-mask of all assigned ARFCNs */
llist_for_each_entry(trx, &bts->trx_list, list) {
- unsigned int i, j;
/* Always add the TRX's ARFCN */
- bitvec_set_bit_pos(bv, trx->arfcn, 1);
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
- const struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ bitvec_set_bit_pos(&bv, trx->arfcn, 1);
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+ const struct gsm_bts_trx_ts *ts = &trx->ts[tn];
/* Add any ARFCNs present in hopping channels */
- for (j = 0; j < 1024; j++) {
- if (bitvec_get_bit_pos(&ts->hopping.arfcns, j))
- bitvec_set_bit_pos(bv, j, 1);
+ for (chan = 0; chan < sizeof(ca) * 8; chan++) {
+ if (bitvec_get_bit_pos(&ts->hopping.arfcns, chan) == ONE)
+ bitvec_set_bit_pos(&bv, chan, ONE);
}
}
}
- /* then we generate a GSM 04.08 frequency list from the bitvec */
+ /* Calculate the overall number of assigned ARFCNs */
+ for (chan_num = 0, chan = 0; chan < sizeof(ca) * 8; chan++) {
+ if (bitvec_get_bit_pos(&bv, chan) == ONE)
+ chan_num++;
+ }
+
+ /* The Mobile Allocation IE may contain up to 64 bits, so here we
+ * cannot allow more than 64 channels in Cell Allocation. */
+ if (chan_num > 64) {
+ LOGP(DRR, LOGL_ERROR, "Failed to (re)generate Cell Allocation: "
+ "number of channels (%u) exceeds the maximum number of "
+ "ARFCNs in Mobile Allocation (64)\n", chan_num);
+ return -E2BIG;
+ }
+
+ /* Commit the new Channel Allocation */
+ memcpy(&bts->si_common.data.cell_alloc[0], ca, sizeof(ca));
+ bts->si_common.cell_chan_num = chan_num;
+
+ return 0;
+}
+
+/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
+int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
+{
+ const struct bitvec *bv = &bts->si_common.cell_alloc;
+
+ /* generate a Frequency List from the Cell Allocation */
return bitvec2freq_list(chan_list, bv, bts, false, false);
}