aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2015-12-13 13:44:07 +0100
committerHarald Welte <laforge@gnumonks.org>2015-12-13 13:51:57 +0100
commit116033d0d1240cf35a20830324c82774a18d3e8e (patch)
tree27a549dffe040d7290da74c0316573670caf397a
parent65d4ef80c6ea0378d4c42d9525e6d94a0de6694e (diff)
Use BS/MS power control parameters in RSL (for Abis/IP)
The TS 08.58 9.3.31 / 9.3.32 IEs are unfortunately encoded in a manufacturer-dependent way. This is why we need to add an encoding function to the bts model. Currently we only implement it for the Abis/IP type BTSs like nanobts and OsmoBTS.
-rw-r--r--openbsc/include/openbsc/abis_rsl.h10
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h6
-rw-r--r--openbsc/src/libbsc/abis_rsl.c53
-rw-r--r--openbsc/src/libbsc/bsc_init.c2
-rw-r--r--openbsc/src/libbsc/bts_ipaccess_nanobts.c29
5 files changed, 87 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h
index b27595e4a..305d8fa00 100644
--- a/openbsc/include/openbsc/abis_rsl.h
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -30,6 +30,7 @@ struct gsm_bts;
struct gsm_lchan;
struct gsm_subscriber;
struct gsm_bts_trx_ts;
+struct gsm_power_control;
int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
@@ -83,8 +84,10 @@ int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf);
int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
const uint8_t *data, int len);
-int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
-int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
+int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db,
+ struct gsm_power_control *pc);
+int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm,
+ struct gsm_power_control *pc);
/* SMSCB functionality */
int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
@@ -96,7 +99,8 @@ int rsl_nokia_si_begin(struct gsm_bts_trx *trx);
int rsl_nokia_si_end(struct gsm_bts_trx *trx);
/* required for Nokia BTS power control */
-int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
+int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel,
+ uint8_t reduction, struct gsm_power_control *pc);
int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 864361414..24ab6d8ff 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -455,6 +455,12 @@ struct gsm_bts_model {
struct tlv_definition nm_att_tlvdef;
+ struct {
+ void (*encode_power_param)(struct msgb *msg,
+ struct gsm_power_control *pc,
+ uint8_t msg_type);
+ } rsl;
+
struct bitvec features;
uint8_t _features_data[128/8];
};
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 8e9258ca5..f95bc7014 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -283,8 +283,30 @@ int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
return abis_rsl_sendmsg(msg);
}
-int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
+/* Add a (MS|BS) Power Parameter IE to the message */
+static void add_power_params(struct gsm_bts_trx *trx, struct msgb *msg,
+ struct gsm_power_control *pc,
+ uint8_t rsl_ie)
{
+ struct gsm_bts *bts = trx->bts;
+
+ /* IE is only present if dynamic power control inside BTS is active */
+ if (rsl_ie == RSL_IE_BS_POWER_PARAM && !trx->power_control.dl.dynamic)
+ return;
+ if (rsl_ie == RSL_IE_MS_POWER_PARAM && !trx->power_control.ul.dynamic)
+ return;
+ /* IE is manufacturer/operator specific, we need an encoder
+ * function as part of the BTS model */
+ if (!bts->model->rsl.encode_power_param)
+ return;
+
+ bts->model->rsl.encode_power_param(msg, pc, rsl_ie);
+}
+
+int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db,
+ struct gsm_power_control *pc)
+{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
struct abis_rsl_dchan_hdr *dh;
struct msgb *msg;
uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
@@ -304,20 +326,24 @@ int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
dh->chan_nr = chan_nr;
msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
+ if (pc)
+ add_power_params(trx, msg, pc, RSL_IE_BS_POWER_PARAM);
- msg->dst = lchan->ts->trx->rsl_link;
+ msg->dst = trx->rsl_link;
return abis_rsl_sendmsg(msg);
}
-int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
+int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm,
+ struct gsm_power_control *pc)
{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
struct abis_rsl_dchan_hdr *dh;
struct msgb *msg;
uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
int ctl_lvl;
- ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
+ ctl_lvl = ms_pwr_ctl_lvl(trx->bts->band, dbm);
if (ctl_lvl < 0)
return ctl_lvl;
@@ -333,8 +359,10 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
dh->chan_nr = chan_nr;
msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
+ if (pc)
+ add_power_params(trx, msg, pc, RSL_IE_MS_POWER_PARAM);
- msg->dst = lchan->ts->trx->rsl_link;
+ msg->dst = trx->rsl_link;
return abis_rsl_sendmsg(msg);
}
@@ -453,6 +481,7 @@ static void mr_config_for_bts(struct gsm_lchan *lchan, struct msgb *msg)
int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
uint8_t ho_ref)
{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
struct abis_rsl_dchan_hdr *dh;
struct msgb *msg;
int rc;
@@ -470,7 +499,7 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
ta = lchan->rqd_ta;
/* BS11 requires TA shifted by 2 bits */
- if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11)
+ if (trx->bts->type == GSM_BTS_TYPE_BS11)
ta <<= 2;
memset(&cd, 0, sizeof(cd));
@@ -525,6 +554,13 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
+
+ add_power_params(trx, msg, &trx->power_control.dl,
+ RSL_IE_BS_POWER_PARAM);
+
+ add_power_params(trx, msg, &trx->power_control.ul,
+ RSL_IE_MS_POWER_PARAM);
+
mr_config_for_bts(lchan, msg);
msg->dst = lchan->ts->trx->rsl_link;
@@ -2163,7 +2199,8 @@ int rsl_nokia_si_end(struct gsm_bts_trx *trx)
return abis_rsl_sendmsg(msg);
}
-int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
+int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel,
+ uint8_t reduction, struct gsm_power_control *pc)
{
struct abis_rsl_common_hdr *ch;
struct msgb *msg = rsl_msgb_alloc();
@@ -2174,6 +2211,8 @@ int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduc
msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
+ if (pc)
+ add_power_params(trx, msg, pc, RSL_IE_BS_POWER_PARAM);
msg->dst = trx->rsl_link;
diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c
index 743f4c155..c792e33ef 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -293,7 +293,7 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
/* channel unspecific, power reduction in 2 dB steps */
- rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2);
+ rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2, NULL);
rsl_nokia_si_end(trx);
}
diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
index dfb5a45bc..2ae37f2d0 100644
--- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c
+++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
@@ -1,6 +1,6 @@
/* ip.access nanoBTS specific code */
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -44,13 +44,19 @@ extern struct gsm_network *bsc_gsmnet;
static int bts_model_nanobts_start(struct gsm_network *net);
static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line);
+static void ipaccess_encode_power_param(struct msgb *msg,
+ struct gsm_power_control *pc,
+ uint8_t msg_type);
struct gsm_bts_model bts_model_nanobts = {
.type = GSM_BTS_TYPE_NANOBTS,
.name = "nanobts",
.start = bts_model_nanobts_start,
.oml_rcvmsg = &abis_nm_rcvmsg,
- .e1line_bind_ops = bts_model_nanobts_e1line_bind_ops,
+ .e1line_bind_ops = bts_model_nanobts_e1line_bind_ops,
+ .rsl = {
+ .encode_power_param = ipaccess_encode_power_param,
+ },
.nm_att_tlvdef = {
.def = {
/* ip.access specifics */
@@ -717,3 +723,22 @@ static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line)
{
e1inp_line_bind_ops(line, &ipaccess_e1inp_line_ops);
}
+
+static void ipaccess_encode_power_param(struct msgb *msg,
+ struct gsm_power_control *pc,
+ uint8_t rsl_ie)
+{
+ uint8_t buf[4];
+
+ if (rsl_ie == RSL_IE_BS_POWER_PARAM)
+ buf[0] = RSL_IPAC_EIE_BS_PWR_CTL;
+ else
+ buf[0] = RSL_IPAC_EIE_MS_PWR_CTL;
+
+ buf[1] = pc->rxlev.lower & 0x3f;
+ buf[2] = pc->rxlev.upper & 0x3f;
+ buf[3] = (pc->rxqual.lower & 7) << 4;
+ buf[3] |= (pc->rxqual.upper & 7);
+
+ msgb_tlv_put(msg, rsl_ie, sizeof(buf), buf);
+}