aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2021-04-06 04:01:50 +0200
committerfixeria <vyanitskiy@sysmocom.de>2021-04-12 12:17:40 +0000
commit6a8536d4da7a2be83ba8647ed12bdc200740dc36 (patch)
tree4ec87e8e2900945ec39bcf075db3df4d25bdb499
parent711ac95c26a9c7f280a3fa82ddae5e2442038c45 (diff)
[hopping] Rework generation of Cell/Mobile Allocation
Calculating the Cell Allocation (basically a bit-vector of all the frequencies allocated to a cell) on the OML link establishment has several downsides and potential problems: * Theoretically, more than 64 ARFCNs can be allocated for a cell via the VTY interface. The problem here is that the Mobile Allocation IE cannot contain more than 64 channels. * The BSC's operator will neither be warned by the interactive VTY shell during configuration, nor during the startup. * The BSC will accept such a configuration, but then will be unable to encode the Mobile Allocation IEs at run-time. This change aims to improve the situation by separating part of the logic from generate_cell_chan_list(), and invoking this part directly from the VTY commands. This way it will become impossible to configure more than 64 ARFCNs, neither via the config file, nor interactively from the VTY. Change-Id: I98211fb0684a973239f5760e1de52a24a1f4c33c
-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);
}