aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-06-15 11:07:03 +0800
committerHarald Welte <laforge@gnumonks.org>2012-06-15 11:07:03 +0800
commit821bf067e408f649bed62f10683fd44b43c0d673 (patch)
tree1240ff85da82df229f36fc051af7d06d43b905d7 /src
parentc882b85d8c867264a0fe038dfe34bf204f5e3f32 (diff)
RSL: Add CCCH LOAD INDICATION for RACH
We now count the total number of RACH slots, the number with rx level above the busy threshold, and the number of valid access bursts. This data is used to generate RSL CCCH LOAD INDICATION for the RACH.
Diffstat (limited to 'src')
-rw-r--r--src/common/load_indication.c10
-rw-r--r--src/common/rsl.c45
-rw-r--r--src/osmo-bts-sysmo/l1_if.c31
3 files changed, 63 insertions, 23 deletions
diff --git a/src/common/load_indication.c b/src/common/load_indication.c
index aa2ec9c1..3e6fa740 100644
--- a/src/common/load_indication.c
+++ b/src/common/load_indication.c
@@ -40,7 +40,7 @@ static void load_timer_cb(void *data)
{
struct gsm_bts *bts = data;
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
- unsigned int pch_percent;
+ unsigned int pch_percent, rach_percent;
/* compute percentages */
pch_percent = (btsb->load.ccch.pch_used * 100) / btsb->load.ccch.pch_total;
@@ -51,6 +51,14 @@ static void load_timer_cb(void *data)
rsl_tx_ccch_load_ind_pch(bts, buffer_space);
}
+ rach_percent = (btsb->load.rach.busy * 100) / btsb->load.rach.total;
+ if (rach_percent >= btsb->load.ccch.load_ind_thresh) {
+ /* send RSL load indication message to BSC */
+ rsl_tx_ccch_load_ind_rach(bts, btsb->load.rach.total,
+ btsb->load.rach.busy,
+ btsb->load.rach.access);
+ }
+
reset_load_counters(bts);
/* re-schedule the timer */
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 370e2f76..509d79f9 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -342,13 +342,35 @@ int rsl_tx_ccch_load_ind_pch(struct gsm_bts *bts, uint16_t paging_avail)
msg = rsl_msgb_alloc(sizeof(struct abis_rsl_common_hdr));
if (!msg)
return -ENOMEM;
- rsl_trx_push_hdr(msg, RSL_MT_CCCH_LOAD_IND);
+ rsl_cch_push_hdr(msg, RSL_MT_CCCH_LOAD_IND, RSL_CHAN_PCH_AGCH);
msgb_tv16_put(msg, RSL_IE_PAGING_LOAD, paging_avail);
msg->trx = bts->c0;
return abis_rsl_sendmsg(msg);
}
+/* 8.5.2 CCCH Load Indication (RACH) */
+int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
+ uint16_t busy, uint16_t access)
+{
+ struct msgb *msg;
+
+ msg = rsl_msgb_alloc(sizeof(struct abis_rsl_common_hdr));
+ if (!msg)
+ return -ENOMEM;
+ rsl_cch_push_hdr(msg, RSL_MT_CCCH_LOAD_IND, RSL_CHAN_RACH);
+ /* tag and length */
+ msgb_tv_put(msg, RSL_IE_RACH_LOAD, 6);
+ /* content of the IE */
+ msgb_put_u16(msg, total);
+ msgb_put_u16(msg, busy);
+ msgb_put_u16(msg, access);
+
+ msg->trx = bts->c0;
+
+ return abis_rsl_sendmsg(msg);
+}
+
/* 8.5.5 PAGING COMMAND */
static int rsl_rx_paging_cmd(struct gsm_bts_trx *trx, struct msgb *msg)
{
@@ -379,27 +401,6 @@ static int rsl_rx_paging_cmd(struct gsm_bts_trx *trx, struct msgb *msg)
return 0;
}
-int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t rach_slots,
- uint16_t rach_busy, uint16_t rach_access)
-{
- struct msgb *msg;
- uint16_t payload[3];
-
- payload[0] = htons(rach_slots);
- payload[1] = htons(rach_busy);
- payload[2] = htons(rach_access);
-
- msg = rsl_msgb_alloc(sizeof(struct abis_rsl_common_hdr));
- if (!msg)
- return -ENOMEM;
-
- msgb_tlv_put(msg, RSL_IE_RACH_LOAD, 6, (uint8_t *)payload);
- rsl_trx_push_hdr(msg, RSL_MT_CCCH_LOAD_IND);
- msg->trx = bts->c0;
-
- return abis_rsl_sendmsg(msg);
-}
-
/* 8.6.2 SACCH FILLING */
static int rsl_rx_sacch_fill(struct gsm_bts_trx *trx, struct msgb *msg)
{
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index f5813b65..6ca6ab28 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -539,6 +539,12 @@ empty_frame:
static int handle_mph_time_ind(struct femtol1_hdl *fl1,
GsmL1_MphTimeInd_t *time_ind)
{
+ struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts *bts = trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
+
+ int frames_expired = time_ind->u32Fn - fl1->gsm_time.fn;
+
/* Update our data structures with the current GSM time */
gsm_fn2gsmtime(&fl1->gsm_time, time_ind->u32Fn);
@@ -549,6 +555,19 @@ static int handle_mph_time_ind(struct femtol1_hdl *fl1,
/* increment the primitive count for the alive timer */
fl1->alive_prim_cnt++;
+ /* increment number of RACH slots that have passed by since the
+ * last time indication */
+ if (trx == bts->c0) {
+ unsigned int num_rach_per_frame;
+ /* 27 / 51 taken from TS 05.01 Figure 3 */
+ if (bts->c0->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4)
+ num_rach_per_frame = 27;
+ else
+ num_rach_per_frame = 51;
+
+ btsb->load.rach.total += frames_expired * num_rach_per_frame;
+ }
+
return 0;
}
@@ -681,12 +700,24 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
{
+ struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts *bts = trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
struct osmo_phsap_prim pp;
struct lapdm_channel *lc;
+ /* increment number of busy RACH slots, if required */
+ if (trx == bts->c0 &&
+ ra_ind->measParam.fRssi >= btsb->load.rach.busy_thresh)
+ btsb->load.rach.busy++;
+
if (ra_ind->measParam.fLinkQuality < MIN_QUAL_RACH)
return 0;
+ /* increment number of RACH slots with valid RACH burst */
+ if (trx == bts->c0)
+ btsb->load.rach.access++;
+
DEBUGP(DL1C, "Rx PH-RA.ind");
dump_meas_res(&ra_ind->measParam);