aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmo-bts/bts.h1
-rw-r--r--include/osmo-bts/gsm_data.h7
-rw-r--r--src/common/bts.c2
-rw-r--r--src/common/bts_trx.c8
-rw-r--r--src/common/gsm_data.c27
-rw-r--r--src/common/nm_bts_fsm.c2
-rw-r--r--src/common/oml.c50
-rw-r--r--src/common/rsl.c7
8 files changed, 92 insertions, 12 deletions
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 14c78a36..2d0eec77 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -158,6 +158,7 @@ struct gsm_bts {
/* Base Station Identification Code (BSIC), lower 3 bits is BCC,
* which is used as TSC for the CCCH */
uint8_t bsic;
+ bool bsic_configured;
/* type of BTS */
enum gsm_bts_type_variant variant;
enum gsm_band band;
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 69e3b00a..5bf6f02b 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -91,7 +91,10 @@ struct gsm_bts_trx_ts {
/* Training Sequence Code (range 0..7) */
uint8_t tsc_oml; /* configured via OML */
- uint8_t tsc; /* currently in use */
+ bool tsc_oml_configured;
+ uint8_t tsc_rsl; /* configured via RSL (Osmo extension) */
+ bool tsc_rsl_configured;
+ uint8_t tsc; /* TSC currently in use. Preference: RSL, OML, BTS-BSIC-OML */
/* Training Sequence Set (range 0..3) */
uint8_t tsc_set;
@@ -194,6 +197,8 @@ int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
+void gsm_ts_apply_configured_tsc(struct gsm_bts_trx_ts *ts);
+
void gsm_ts_release(struct gsm_bts_trx_ts *ts);
#endif /* _GSM_DATA_H */
diff --git a/src/common/bts.c b/src/common/bts.c
index 9cc694fb..de27ad8f 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -351,6 +351,8 @@ int bts_init(struct gsm_bts *bts)
power_ctrl_params_def_reset(&bts->ms_dpc_params, false);
/* configurable via OML */
+ bts->bsic = 0xff; /* invalid value, guarded by bsc_configured=false */
+ bts->bsic_configured = false;
bts->load.ccch.load_ind_period = 112;
bts->rtp_jitter_buf_ms = 100;
bts->max_ta = 63;
diff --git a/src/common/bts_trx.c b/src/common/bts_trx.c
index 280880fc..089f2289 100644
--- a/src/common/bts_trx.c
+++ b/src/common/bts_trx.c
@@ -74,6 +74,10 @@ static void gsm_bts_trx_init_ts(struct gsm_bts_trx *trx)
ts->trx = trx;
ts->nr = tn;
+ ts->tsc_oml_configured = false;
+ ts->tsc_rsl_configured = false;
+ ts->tsc = ts->tsc_oml = ts->tsc_rsl = 0xff;
+
ts->mo.fi = osmo_fsm_inst_alloc(&nm_chan_fsm, trx, ts,
LOGL_INFO, NULL);
osmo_fsm_inst_update_id_f(ts->mo.fi, "%s-ts%u",
@@ -99,6 +103,10 @@ void gsm_bts_trx_init_shadow_ts(struct gsm_bts_trx *trx)
ts->trx = trx;
ts->nr = tn;
+ ts->tsc_oml_configured = false;
+ ts->tsc_rsl_configured = false;
+ ts->tsc = ts->tsc_oml = ts->tsc_rsl = 0xff;
+
/* Link both primary and shadow */
trx->ts[tn].vamos.peer = ts;
ts->vamos.peer = &trx->ts[tn];
diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c
index e5dbf105..dad5587b 100644
--- a/src/common/gsm_data.c
+++ b/src/common/gsm_data.c
@@ -306,6 +306,29 @@ bool ts_is_pdch(const struct gsm_bts_trx_ts *ts)
}
}
+/* Apply ts->tsc based on what was configured coming from different sources.
+ * Priorities (preferred first, overrides ones afterward):
+ * 1- RSL OSMO_TSC IE
+ * 2- OML SetChannelAttr TSC IE
+ * 3- OML SetBtsAttr BSIC IE
+ */
+void gsm_ts_apply_configured_tsc(struct gsm_bts_trx_ts *ts)
+{
+ if (ts->tsc_rsl_configured) {
+ ts->tsc = ts->tsc_rsl;
+ return;
+ }
+ if (ts->tsc_oml_configured) {
+ ts->tsc = ts->tsc_oml;
+ return;
+ }
+ if (ts->trx->bts->bsic_configured) {
+ ts->tsc = BTS_TSC(ts->trx->bts);
+ return;
+ }
+ ts->tsc = 0xff; /* invalid value */
+}
+
void gsm_ts_release(struct gsm_bts_trx_ts *ts)
{
unsigned int ln;
@@ -318,4 +341,8 @@ void gsm_ts_release(struct gsm_bts_trx_ts *ts)
/* Make sure pchan_is is reset, since PCU act_req to release it will be
* ignored as the lchan will already be released. */
ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE;
+
+ ts->tsc_oml_configured = false;
+ ts->tsc_rsl_configured = false;
+ ts->tsc = ts->tsc_oml = ts->tsc_rsl = 0xff;
}
diff --git a/src/common/nm_bts_fsm.c b/src/common/nm_bts_fsm.c
index 063ffe84..ea3a6c3a 100644
--- a/src/common/nm_bts_fsm.c
+++ b/src/common/nm_bts_fsm.c
@@ -60,6 +60,8 @@ static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint3
struct gsm_bts *bts = (struct gsm_bts *)fi->priv;
/* Reset state: */
bts->si_valid = 0;
+ bts->bsic_configured = false;
+ bts->bsic = 0xff; /* invalid value */
TALLOC_FREE(bts->mo.nm_attr);
bts_cbch_reset(bts);
diff --git a/src/common/oml.c b/src/common/oml.c
index 724e4f81..5ffb6ff3 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -712,8 +712,35 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
bts->c0->arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
/* 9.4.9 BSIC */
- if (TLVP_PRES_LEN(&tp, NM_ATT_BSIC, 1))
+ if (TLVP_PRES_LEN(&tp, NM_ATT_BSIC, 1)) {
+ struct gsm_bts_trx *trx;
+ uint8_t bts_tsc;
+
bts->bsic = *TLVP_VAL(&tp, NM_ATT_BSIC);
+ bts->bsic_configured = true;
+ bts_tsc = BTS_TSC(bts);
+
+ /* Apply TSC update on each TS if required: */
+ llist_for_each_entry(trx, &bts->trx_list, list) { /* C0..n */
+ unsigned int tn;
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[tn];
+
+ /* First some config validation: */
+ if (ts->tsc_oml_configured &&
+ ts->tsc_oml != bts_tsc &&
+ !osmo_bts_has_feature(bts->features, BTS_FEAT_MULTI_TSC)) {
+ LOGPFOH(DOML, LOGL_ERROR, foh, "SET BTS ATTR: this BTS model does not "
+ "support TSC %u != BSIC-BCC %u (TSC %u)\n",
+ ts->tsc_oml, bts->bsic, bts_tsc);
+ return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
+ }
+
+ /* Now update TS TSC if needed: */
+ gsm_ts_apply_configured_tsc(ts);
+ }
+ }
+ }
/* call into BTS driver to apply new attributes to hardware */
return bts_model_apply_oml(bts, msg, tp_merged, NM_OC_BTS, bts);
@@ -984,20 +1011,25 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
/* 9.4.60 TSC */
if (TLVP_PRES_LEN(&tp, NM_ATT_TSC, 1)) {
- ts->tsc_oml = ts->tsc = *TLVP_VAL(&tp, NM_ATT_TSC);
- if (ts->tsc != BTS_TSC(bts) &&
+ ts->tsc_oml = *TLVP_VAL(&tp, NM_ATT_TSC);
+ ts->tsc_oml_configured = true;
+ }
+
+ if (ts->tsc_oml_configured) {
+ if (bts->bsic_configured &&
+ ts->tsc_oml != BTS_TSC(bts) &&
!osmo_bts_has_feature(bts->features, BTS_FEAT_MULTI_TSC)) {
LOGPFOH(DOML, LOGL_ERROR, foh, "SET CHAN ATTR: this BTS model does not "
- "support TSC %u != BSIC-BCC %u\n", ts->tsc, BTS_TSC(bts));
+ "support TSC %u != BSIC-BCC %u\n", ts->tsc_oml, BTS_TSC(bts));
talloc_free(tp_merged);
return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
}
- } else {
- /* If there is no TSC specified, use the BCC */
- ts->tsc_oml = ts->tsc = BTS_TSC(bts);
+ gsm_ts_apply_configured_tsc(ts);
}
- LOGPFOH(DOML, LOGL_INFO, foh, "SET CHAN ATTR (TSC=%u pchan=%s",
- ts->tsc, gsm_pchan_name(ts->pchan));
+
+ LOGPFOH(DOML, LOGL_INFO, foh, "SET CHAN ATTR (TSC=%d pchan=%s",
+ ts->tsc_oml_configured ? (int)ts->tsc_oml : -1,
+ gsm_pchan_name(ts->pchan));
if (ts->hopping.enabled)
LOGPC(DOML, LOGL_INFO, " hsn=%u maio=%u chan_num=%u",
ts->hopping.hsn, ts->hopping.maio, ts->hopping.arfcn_num);
diff --git a/src/common/rsl.c b/src/common/rsl.c
index a8c16a78..da5ad687 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -294,11 +294,14 @@ static int rsl_handle_osmo_tsc_ie(struct gsm_lchan *lchan,
if (TLVP_PRES_LEN(tp, RSL_IE_OSMO_TRAINING_SEQUENCE, 2)) {
const uint8_t *ie = TLVP_VAL(tp, RSL_IE_OSMO_TRAINING_SEQUENCE);
lchan->ts->tsc_set = ie[0] & 0x03; /* Range: 0..3 */
- lchan->ts->tsc = ie[1] & 0x07; /* Range: 0..7 */
+ lchan->ts->tsc_rsl = ie[1] & 0x07; /* Range: 0..7 */
+ lchan->ts->tsc_rsl_configured = true;
} else {
- lchan->ts->tsc = lchan->ts->tsc_oml;
+ lchan->ts->tsc_rsl_configured = false;
+ lchan->ts->tsc_rsl = 0xff;
lchan->ts->tsc_set = 0;
}
+ gsm_ts_apply_configured_tsc(lchan->ts);
return 0;
}