OpenBSC
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- 1 participants
- 4322 discussions
03 Feb '16
From: Harald Welte <laforge(a)gnumonks.org>
The L1 scheduler is a generally useful component that is unfortunately
tied quite a bit into the OsmoTRX support. Let's try to separate it out
by having separate per-trx/per-ts/per-chan data structures pre-fixed
with l1sched_
Using this patch it should be one step easier to use the scheduler for
other BTS models, such as the intended upcoming virtual BTS.
---
src/osmo-bts-trx/l1_if.c | 35 ++--
src/osmo-bts-trx/l1_if.h | 121 +----------
src/osmo-bts-trx/loops.c | 83 ++++----
src/osmo-bts-trx/loops.h | 14 +-
src/osmo-bts-trx/scheduler.c | 486 +++++++++++++++++++++++--------------------
src/osmo-bts-trx/scheduler.h | 143 ++++++++++++-
src/osmo-bts-trx/trx_if.c | 2 +-
7 files changed, 473 insertions(+), 411 deletions(-)
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index a45ba05..70a5c59 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -68,9 +68,10 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
if (!l1h)
return NULL;
l1h->trx = trx;
+ l1h->l1s.trx = trx;
trx->role_bts.l1h = l1h;
- trx_sched_init(l1h);
+ trx_sched_init(&l1h->l1s);
rc = trx_if_open(l1h);
if (rc < 0) {
@@ -89,7 +90,7 @@ err:
void l1if_close(struct trx_l1h *l1h)
{
trx_if_close(l1h);
- trx_sched_exit(l1h);
+ trx_sched_exit(&l1h->l1s);
talloc_free(l1h);
}
@@ -267,7 +268,7 @@ int bts_model_trx_close(struct gsm_bts_trx *trx)
enum gsm_phys_chan_config pchan = trx->ts[0].pchan;
/* close all logical channels and reset timeslots */
- trx_sched_reset(l1h);
+ trx_sched_reset(&l1h->l1s);
/* deactivate lchan for CCCH */
if (pchan == GSM_PCHAN_CCCH || pchan == GSM_PCHAN_CCCH_SDCCH4) {
@@ -374,8 +375,12 @@ static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts)
l1if_provision_transceiver_trx(l1h);
}
+ /* ignore disabled slots */
+ if (!(l1h->config.slotmask & (1 << tn)))
+ return NM_NACK_RES_NOTAVAIL;
+
/* set physical channel */
- rc = trx_sched_set_pchan(l1h, tn, pchan);
+ rc = trx_sched_set_pchan(&l1h->l1s, tn, pchan);
if (rc)
return NM_NACK_RES_NOTAVAIL;
@@ -413,17 +418,17 @@ static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan,
if (!downlink) {
/* set uplink */
- trx_sched_set_cipher(l1h, chan_nr, 0, lchan->encr.alg_id - 1,
+ trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, lchan->encr.alg_id - 1,
lchan->encr.key, lchan->encr.key_len);
lchan->ciph_state = LCHAN_CIPH_RX_CONF;
} else {
/* set downlink and also set uplink, if not already */
if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) {
- trx_sched_set_cipher(l1h, chan_nr, 0,
+ trx_sched_set_cipher(&l1h->l1s, chan_nr, 0,
lchan->encr.alg_id - 1, lchan->encr.key,
lchan->encr.key_len);
}
- trx_sched_set_cipher(l1h, chan_nr, 1, lchan->encr.alg_id - 1,
+ trx_sched_set_cipher(&l1h->l1s, chan_nr, 1, lchan->encr.alg_id - 1,
lchan->encr.key, lchan->encr.key_len);
lchan->ciph_state = LCHAN_CIPH_RXTX_CONF;
}
@@ -510,12 +515,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
if (!msg)
break;
/* put data into scheduler's queue */
- return trx_sched_ph_data_req(l1h, l1sap);
+ return trx_sched_ph_data_req(&l1h->l1s, l1sap);
case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST):
if (!msg)
break;
/* put data into scheduler's queue */
- return trx_sched_tch_req(l1h, l1sap);
+ return trx_sched_tch_req(&l1h->l1s, l1sap);
case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST):
switch (l1sap->u.info.type) {
case PRIM_INFO_ACT_CIPH:
@@ -542,11 +547,11 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
break;
}
/* activate dedicated channel */
- trx_sched_set_lchan(l1h, chan_nr, 0x00, 1);
+ trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x00, 1);
/* activate associated channel */
- trx_sched_set_lchan(l1h, chan_nr, 0x40, 1);
+ trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x40, 1);
/* set mode */
- trx_sched_set_mode(l1h, chan_nr,
+ trx_sched_set_mode(&l1h->l1s, chan_nr,
lchan->rsl_cmode, lchan->tch_mode,
lchan->tch.amr_mr.num_modes,
lchan->tch.amr_mr.bts_mode[0].mode,
@@ -574,7 +579,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
}
if (l1sap->u.info.type == PRIM_INFO_MODIFY) {
/* change mode */
- trx_sched_set_mode(l1h, chan_nr,
+ trx_sched_set_mode(&l1h->l1s, chan_nr,
lchan->rsl_cmode, lchan->tch_mode,
lchan->tch.amr_mr.num_modes,
lchan->tch.amr_mr.bts_mode[0].mode,
@@ -591,12 +596,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
break;
}
/* deactivate associated channel */
- trx_sched_set_lchan(l1h, chan_nr, 0x40, 0);
+ trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x40, 0);
if (!l1sap->u.info.u.act_req.sacch_only) {
/* set lchan inactive */
lchan_set_state(lchan, LCHAN_S_NONE);
/* deactivate dedicated channel */
- trx_sched_set_lchan(l1h, chan_nr, 0x00, 0);
+ trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x00, 0);
/* confirm only on dedicated channel */
mph_info_chan_confirm(l1h, chan_nr,
PRIM_INFO_DEACTIVATE, 0);
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h
index 2c672cb..6dec273 100644
--- a/src/osmo-bts-trx/l1_if.h
+++ b/src/osmo-bts-trx/l1_if.h
@@ -1,109 +1,7 @@
#ifndef L1_IF_H_TRX
#define L1_IF_H_TRX
-/* These types define the different channels on a multiframe.
- * Each channel has queues and can be activated individually.
- */
-enum trx_chan_type {
- TRXC_IDLE = 0,
- TRXC_FCCH,
- TRXC_SCH,
- TRXC_BCCH,
- TRXC_RACH,
- TRXC_CCCH,
- TRXC_TCHF,
- TRXC_TCHH_0,
- TRXC_TCHH_1,
- TRXC_SDCCH4_0,
- TRXC_SDCCH4_1,
- TRXC_SDCCH4_2,
- TRXC_SDCCH4_3,
- TRXC_SDCCH8_0,
- TRXC_SDCCH8_1,
- TRXC_SDCCH8_2,
- TRXC_SDCCH8_3,
- TRXC_SDCCH8_4,
- TRXC_SDCCH8_5,
- TRXC_SDCCH8_6,
- TRXC_SDCCH8_7,
- TRXC_SACCHTF,
- TRXC_SACCHTH_0,
- TRXC_SACCHTH_1,
- TRXC_SACCH4_0,
- TRXC_SACCH4_1,
- TRXC_SACCH4_2,
- TRXC_SACCH4_3,
- TRXC_SACCH8_0,
- TRXC_SACCH8_1,
- TRXC_SACCH8_2,
- TRXC_SACCH8_3,
- TRXC_SACCH8_4,
- TRXC_SACCH8_5,
- TRXC_SACCH8_6,
- TRXC_SACCH8_7,
- TRXC_PDTCH,
- TRXC_PTCCH,
- _TRX_CHAN_MAX
-};
-
-/* States each channel on a multiframe */
-struct trx_chan_state {
- /* scheduler */
- uint8_t active; /* Channel is active */
- ubit_t *dl_bursts; /* burst buffer for TX */
- sbit_t *ul_bursts; /* burst buffer for RX */
- uint32_t ul_first_fn; /* fn of first burst */
- uint8_t ul_mask; /* mask of received bursts */
-
- /* RSSI / TOA */
- uint8_t rssi_num; /* number of RSSI values */
- float rssi_sum; /* sum of RSSI values */
- uint8_t toa_num; /* number of TOA values */
- float toa_sum; /* sum of TOA values */
-
- /* loss detection */
- uint8_t lost; /* (SACCH) loss detection */
-
- /* mode */
- uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
-
- /* AMR */
- uint8_t codec[4]; /* 4 possible codecs for amr */
- int codecs; /* number of possible codecs */
- float ber_sum; /* sum of bit error rates */
- int ber_num; /* number of bit error rates */
- uint8_t ul_ft; /* current uplink FT index */
- uint8_t dl_ft; /* current downlink FT index */
- uint8_t ul_cmr; /* current uplink CMR index */
- uint8_t dl_cmr; /* current downlink CMR index */
- uint8_t amr_loop; /* if AMR loop is enabled */
-
- /* TCH/H */
- uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
- uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
-
- /* encryption */
- int ul_encr_algo; /* A5/x encry algo downlink */
- int dl_encr_algo; /* A5/x encry algo uplink */
- int ul_encr_key_len;
- int dl_encr_key_len;
- uint8_t ul_encr_key[MAX_A5_KEY_LEN];
- uint8_t dl_encr_key[MAX_A5_KEY_LEN];
-
- /* measurements */
- struct {
- uint8_t clock; /* cyclic clock counter */
- int8_t rssi[32]; /* last RSSI values */
- int rssi_count; /* received RSSI values */
- int rssi_valid_count; /* number of stored value */
- int rssi_got_burst; /* any burst received so far */
- float toa_sum; /* sum of TOA values */
- int toa_num; /* number of TOA value */
- } meas;
-
- /* handover */
- uint8_t ho_rach_detect; /* if rach detection is on */
-};
+#include "scheduler.h"
struct trx_config {
uint8_t poweron; /* poweron(1) or poweroff(0) */
@@ -152,16 +50,9 @@ struct trx_l1h {
/* transceiver config */
struct trx_config config;
-
- uint8_t mf_index[TRX_NR_TS]; /* selected multiframe index */
- uint32_t mf_last_fn[TRX_NR_TS]; /* last received frame */
- uint8_t mf_period[TRX_NR_TS]; /* period of multiframe */
- const struct trx_sched_frame *mf_frames[TRX_NR_TS]; /* pointer to frame layout */
-
- /* Channel states for all channels on all timeslots */
- struct trx_chan_state chan_states[TRX_NR_TS][_TRX_CHAN_MAX];
- struct llist_head dl_prims[TRX_NR_TS]; /* Queue primitves for TX */
uint8_t ho_rach_detect[TRX_NR_TS][TS_MAX_LCHAN];
+
+ struct l1sched_trx l1s;
};
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);
@@ -176,4 +67,10 @@ void l1if_fill_meas_res(struct osmo_phsap_prim *l1sap, uint8_t chan_nr, float ta
int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr,
int n_errors, int n_bits_total, float rssi, float toa);
+static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
+{
+ struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ return &l1h->l1s;
+}
+
#endif /* L1_IF_H_TRX */
diff --git a/src/osmo-bts-trx/loops.c b/src/osmo-bts-trx/loops.c
index 52ac170..8070e80 100644
--- a/src/osmo-bts-trx/loops.c
+++ b/src/osmo-bts-trx/loops.c
@@ -33,7 +33,7 @@
#include "l1_if.h"
#include "loops.h"
-#define MS_PWR_DBM(lvl) ms_pwr_dbm(gsm_arfcn2band(l1h->config.arfcn), lvl)
+#define MS_PWR_DBM(arfcn, lvl) ms_pwr_dbm(gsm_arfcn2band(arfcn), lvl)
/*
* MS Power loop
@@ -42,11 +42,12 @@
int trx_ms_power_loop = 0;
int8_t trx_target_rssi = -10;
-static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
- uint8_t chan_nr, struct trx_chan_state *chan_state, int8_t diff)
+static int ms_power_diff(struct gsm_lchan *lchan, uint8_t chan_nr, int8_t diff)
{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
+ uint16_t arfcn = trx->arfcn;
int8_t new_power;
-
+
new_power = lchan->ms_power - (diff >> 1);
if (diff == 0)
@@ -56,7 +57,7 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
new_power = 0;
// FIXME: to go above 1W, we need to know classmark of MS
- if (l1h->config.arfcn >= 512 && l1h->config.arfcn <= 885) {
+ if (arfcn >= 512 && arfcn <= 885) {
if (new_power > 15)
new_power = 15;
} else {
@@ -73,8 +74,8 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
if (lchan->ms_power == new_power) {
LOGP(DLOOP, LOGL_INFO, "Keeping MS new_power of trx=%u "
"chan_nr=0x%02x at control level %d (%d dBm)\n",
- l1h->trx->nr, chan_nr, new_power,
- MS_PWR_DBM(new_power));
+ trx->nr, chan_nr, new_power,
+ MS_PWR_DBM(arfcn, new_power));
return 0;
}
@@ -82,15 +83,16 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
LOGP(DLOOP, LOGL_INFO, "%s MS new_power of trx=%u chan_nr=0x%02x from "
"control level %d (%d dBm) to %d (%d dBm)\n",
(diff > 0) ? "Raising" : "Lowering",
- l1h->trx->nr, chan_nr, lchan->ms_power,
- MS_PWR_DBM(lchan->ms_power), new_power, MS_PWR_DBM(new_power));
+ trx->nr, chan_nr, lchan->ms_power,
+ MS_PWR_DBM(arfcn, lchan->ms_power), new_power,
+ MS_PWR_DBM(arfcn, new_power));
lchan->ms_power = new_power;
return 0;
}
-static int ms_power_val(struct trx_chan_state *chan_state, int8_t rssi)
+static int ms_power_val(struct l1sched_chan_state *chan_state, int8_t rssi)
{
/* ignore inserted dummy frames, treat as lost frames */
if (rssi < -127)
@@ -112,9 +114,10 @@ static int ms_power_val(struct trx_chan_state *chan_state, int8_t rssi)
return 0;
}
-static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
- uint8_t chan_nr, struct trx_chan_state *chan_state)
+static int ms_power_clock(struct gsm_lchan *lchan,
+ uint8_t chan_nr, struct l1sched_chan_state *chan_state)
{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
int rssi;
int i;
@@ -134,9 +137,8 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
if (chan_state->meas.rssi_count == 0) {
LOGP(DLOOP, LOGL_NOTICE, "LOST SACCH frame of trx=%u "
"chan_nr=0x%02x, so we raise MS power\n",
- l1h->trx->nr, chan_nr);
- return ms_power_diff(l1h, lchan, chan_nr, chan_state,
- MS_RAISE_MAX);
+ trx->nr, chan_nr);
+ return ms_power_diff(lchan, chan_nr, MS_RAISE_MAX);
}
/* reset total counter */
@@ -157,9 +159,10 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
/* change RSSI */
LOGP(DLOOP, LOGL_DEBUG, "Lowest RSSI: %d Target RSSI: %d Current "
"MS power: %d (%d dBm) of trx=%u chan_nr=0x%02x\n", rssi,
- trx_target_rssi, lchan->ms_power, MS_PWR_DBM(lchan->ms_power),
- l1h->trx->nr, chan_nr);
- ms_power_diff(l1h, lchan, chan_nr, chan_state, trx_target_rssi - rssi);
+ trx_target_rssi, lchan->ms_power,
+ MS_PWR_DBM(trx->arfcn, lchan->ms_power),
+ trx->nr, chan_nr);
+ ms_power_diff(lchan, chan_nr, trx_target_rssi - rssi);
return 0;
}
@@ -171,9 +174,11 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
int trx_ta_loop = 1;
-int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
- struct trx_chan_state *chan_state, float toa)
+int ta_val(struct gsm_lchan *lchan, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state, float toa)
{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
+
/* check if the current L1 header acks to the current ordered TA */
if (lchan->meas.l1_info[1] != lchan->rqd_ta)
return 0;
@@ -190,19 +195,19 @@ int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
if (toa < -0.9F && lchan->rqd_ta > 0) {
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too "
"early (%.2f), now lowering TA from %d to %d\n",
- l1h->trx->nr, chan_nr, toa, lchan->rqd_ta,
+ trx->nr, chan_nr, toa, lchan->rqd_ta,
lchan->rqd_ta - 1);
lchan->rqd_ta--;
} else if (toa > 0.9F && lchan->rqd_ta < 63) {
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too "
"late (%.2f), now raising TA from %d to %d\n",
- l1h->trx->nr, chan_nr, toa, lchan->rqd_ta,
+ trx->nr, chan_nr, toa, lchan->rqd_ta,
lchan->rqd_ta + 1);
lchan->rqd_ta++;
} else
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is "
"correct (%.2f), keeping current TA of %d\n",
- l1h->trx->nr, chan_nr, toa, lchan->rqd_ta);
+ trx->nr, chan_nr, toa, lchan->rqd_ta);
chan_state->meas.toa_num = 0;
chan_state->meas.toa_sum = 0;
@@ -210,29 +215,29 @@ int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
return 0;
}
-int trx_loop_sacch_input(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state, int8_t rssi, float toa)
+int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state, int8_t rssi, float toa)
{
- struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
+ struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
.lchan[l1sap_chan2ss(chan_nr)];
if (trx_ms_power_loop)
ms_power_val(chan_state, rssi);
if (trx_ta_loop)
- ta_val(l1h, lchan, chan_nr, chan_state, toa);
+ ta_val(lchan, chan_nr, chan_state, toa);
return 0;
}
-int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state)
+int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state)
{
- struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
+ struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
.lchan[l1sap_chan2ss(chan_nr)];
if (trx_ms_power_loop)
- ms_power_clock(l1h, lchan, chan_nr, chan_state);
+ ms_power_clock(lchan, chan_nr, chan_state);
/* count the number of SACCH clocks */
chan_state->meas.clock++;
@@ -240,10 +245,11 @@ int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
return 0;
}
-int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state, float ber)
+int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state, float ber)
{
- struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
+ struct gsm_bts_trx *trx = l1t->trx;
+ struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)]
.lchan[l1sap_chan2ss(chan_nr)];
int c_i;
@@ -280,7 +286,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
LOGP(DLOOP, LOGL_DEBUG, "Current bit error rate (BER) %.6f "
"codec id %d of trx=%u chan_nr=0x%02x\n", ber,
- chan_state->ul_ft, l1h->trx->nr, chan_nr);
+ chan_state->ul_ft, trx->nr, chan_nr);
/* degrade */
if (chan_state->dl_cmr > 0) {
@@ -290,7 +296,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
LOGP(DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f "
"from codec id %d to %d of trx=%u "
"chan_nr=0x%02x\n", ber, chan_state->dl_cmr,
- chan_state->dl_cmr - 1, l1h->trx->nr, chan_nr);
+ chan_state->dl_cmr - 1, trx->nr, chan_nr);
chan_state->dl_cmr--;
}
@@ -306,7 +312,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
LOGP(DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f "
"from codec id %d to %d of trx=%u "
"chan_nr=0x%02x\n", ber, chan_state->dl_cmr,
- chan_state->dl_cmr + 1, l1h->trx->nr, chan_nr);
+ chan_state->dl_cmr + 1, trx->nr, chan_nr);
chan_state->dl_cmr++;
}
@@ -316,7 +322,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
return 0;
}
-int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop)
+int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop)
{
if (chan_state->amr_loop && !loop) {
chan_state->amr_loop = 0;
@@ -336,4 +342,3 @@ int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop)
return 0;
}
-
diff --git a/src/osmo-bts-trx/loops.h b/src/osmo-bts-trx/loops.h
index 27b0ef2..613d2d0 100644
--- a/src/osmo-bts-trx/loops.h
+++ b/src/osmo-bts-trx/loops.h
@@ -17,15 +17,15 @@ extern int trx_ms_power_loop;
extern int8_t trx_target_rssi;
extern int trx_ta_loop;
-int trx_loop_sacch_input(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state, int8_t rssi, float toa);
+int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state, int8_t rssi, float toa);
-int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state);
+int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state);
-int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
- struct trx_chan_state *chan_state, float ber);
+int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
+ struct l1sched_chan_state *chan_state, float ber);
-int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop);
+int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop);
#endif /* _TRX_LOOPS_H */
diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c
index 1710b4e..6d0f180 100644
--- a/src/osmo-bts-trx/scheduler.c
+++ b/src/osmo-bts-trx/scheduler.c
@@ -2,6 +2,7 @@
/* (C) 2013 by Andreas Eversberg <jolly(a)eversberg.eu>
* (C) 2015 by Alexander Chemeris <Alexander.Chemeris(a)fairwaves.co>
+ * (C) 2015 by Harald Welte <laforge(a)gnumonks.org>
*
* All Rights Reserved
*
@@ -67,47 +68,47 @@ uint32_t trx_clock_advance = 20;
/* advance RTS to give some time for data processing. (especially PCU) */
uint32_t trx_rts_advance = 5; /* about 20ms */
-typedef int trx_sched_rts_func(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan);
-typedef ubit_t *trx_sched_dl_func(struct trx_l1h *l1h, uint8_t tn,
+typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
uint32_t fn, enum trx_chan_type chan, uint8_t bid);
-typedef int trx_sched_ul_func(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
-static int rts_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan);
-static int rts_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan);
-static int rts_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan);
-static ubit_t *tx_idle_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_fcch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_sch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static ubit_t *tx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid);
-static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
-static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
-static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
-static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
-static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa);
@@ -219,23 +220,22 @@ static const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
* init / exit
*/
-int trx_sched_init(struct trx_l1h *l1h)
+int trx_sched_init(struct l1sched_trx *l1t)
{
uint8_t tn;
int i;
- struct trx_chan_state *chan_state;
- LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1h->trx->nr);
+ LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1t->trx->nr);
- /* hack to get bts */
- bts = l1h->trx->bts;
+ for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
- for (tn = 0; tn < TRX_NR_TS; tn++) {
- l1h->mf_index[tn] = 0;
- l1h->mf_last_fn[tn] = 0;
- INIT_LLIST_HEAD(&l1h->dl_prims[tn]);
- for (i = 0; i < _TRX_CHAN_MAX; i++) {
- chan_state = &l1h->chan_states[tn][i];
+ l1ts->mf_index = 0;
+ l1ts->mf_last_fn = 0;
+ INIT_LLIST_HEAD(&l1ts->dl_prims);
+ for (i = 0; i < ARRAY_SIZE(&l1ts->chan_state); i++) {
+ struct l1sched_chan_state *chan_state;
+ chan_state = &l1ts->chan_state[i];
chan_state->active = 0;
}
}
@@ -243,18 +243,20 @@ int trx_sched_init(struct trx_l1h *l1h)
return 0;
}
-void trx_sched_exit(struct trx_l1h *l1h)
+void trx_sched_exit(struct l1sched_trx *l1t)
{
+ struct gsm_bts_trx_ts *ts;
uint8_t tn;
int i;
- struct trx_chan_state *chan_state;
- LOGP(DL1C, LOGL_NOTICE, "Exit scheduler for trx=%u\n", l1h->trx->nr);
+ LOGP(DL1C, LOGL_NOTICE, "Exit scheduler for trx=%u\n", l1t->trx->nr);
- for (tn = 0; tn < TRX_NR_TS; tn++) {
- msgb_queue_flush(&l1h->dl_prims[tn]);
+ for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ msgb_queue_flush(&l1ts->dl_prims);
for (i = 0; i < _TRX_CHAN_MAX; i++) {
- chan_state = &l1h->chan_states[tn][i];
+ struct l1sched_chan_state *chan_state;
+ chan_state = &l1ts->chan_state[i];
if (chan_state->dl_bursts) {
talloc_free(chan_state->dl_bursts);
chan_state->dl_bursts = NULL;
@@ -265,16 +267,17 @@ void trx_sched_exit(struct trx_l1h *l1h)
}
}
/* clear lchan channel states */
- for (i = 0; i < TRX_NR_TS; i++)
- l1h->trx->ts[tn].lchan[i].state = LCHAN_S_NONE;
+ ts = &l1t->trx->ts[tn];
+ for (i = 0; i < ARRAY_SIZE(ts->lchan); i++)
+ lchan_set_state(&ts->lchan[i], LCHAN_S_NONE);
}
}
/* close all logical channels and reset timeslots */
-void trx_sched_reset(struct trx_l1h *l1h)
+void trx_sched_reset(struct l1sched_trx *l1t)
{
- trx_sched_exit(l1h);
- trx_sched_init(l1h);
+ trx_sched_exit(l1t);
+ trx_sched_init(l1t);
}
@@ -282,13 +285,14 @@ void trx_sched_reset(struct trx_l1h *l1h)
* data request (from upper layer)
*/
-int trx_sched_ph_data_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap)
+int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap)
{
uint8_t tn = l1sap->u.data.chan_nr & 7;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
LOGP(DL1C, LOGL_INFO, "PH-DATA.req: chan_nr=0x%02x link_id=0x%02x "
"fn=%u ts=%u trx=%u\n", l1sap->u.data.chan_nr,
- l1sap->u.data.link_id, l1sap->u.data.fn, tn, l1h->trx->nr);
+ l1sap->u.data.link_id, l1sap->u.data.fn, tn, l1t->trx->nr);
if (!l1sap->oph.msg)
abort();
@@ -299,18 +303,19 @@ int trx_sched_ph_data_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap)
return 0;
}
- msgb_enqueue(&l1h->dl_prims[tn], l1sap->oph.msg);
+ msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg);
return 0;
}
-int trx_sched_tch_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap)
+int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap)
{
uint8_t tn = l1sap->u.tch.chan_nr & 7;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
LOGP(DL1C, LOGL_INFO, "TCH.req: chan_nr=0x%02x "
"fn=%u ts=%u trx=%u\n", l1sap->u.tch.chan_nr,
- l1sap->u.tch.fn, tn, l1h->trx->nr);
+ l1sap->u.tch.fn, tn, l1t->trx->nr);
if (!l1sap->oph.msg)
abort();
@@ -321,7 +326,7 @@ int trx_sched_tch_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap)
return 0;
}
- msgb_enqueue(&l1h->dl_prims[tn], l1sap->oph.msg);
+ msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg);
return 0;
}
@@ -332,12 +337,13 @@ int trx_sched_tch_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap)
*/
/* RTS for data frame */
-static int rts_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan)
{
uint8_t chan_nr, link_id;
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
/* get data for RTS indication */
chan_nr = trx_chan_desc[chan].chan_nr | tn;
@@ -351,11 +357,11 @@ static int rts_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
LOGP(DL1C, LOGL_INFO, "PH-RTS.ind: chan=%s chan_nr=0x%02x "
"link_id=0x%02x fn=%u ts=%u trx=%u\n", trx_chan_desc[chan].name,
- chan_nr, link_id, fn, tn, l1h->trx->nr);
+ chan_nr, link_id, fn, tn, l1t->trx->nr);
/* send clock information to loops process */
if (L1SAP_IS_LINK_SACCH(link_id))
- trx_loop_sacch_clock(l1h, chan_nr, &l1h->chan_states[tn][chan]);
+ trx_loop_sacch_clock(l1t, chan_nr, &l1ts->chan_state[chan]);
/* generate prim */
msg = l1sap_msgb_alloc(200);
@@ -368,15 +374,16 @@ static int rts_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
l1sap->u.data.link_id = link_id;
l1sap->u.data.fn = fn;
- return l1sap_up(l1h->trx, l1sap);
+ return l1sap_up(l1t->trx, l1sap);
}
-static int rts_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, int facch)
{
uint8_t chan_nr, link_id;
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
int rc = 0;
/* get data for RTS indication */
@@ -391,7 +398,7 @@ static int rts_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
LOGP(DL1C, LOGL_INFO, "TCH RTS.ind: chan=%s chan_nr=0x%02x "
"fn=%u ts=%u trx=%u\n", trx_chan_desc[chan].name,
- chan_nr, fn, tn, l1h->trx->nr);
+ chan_nr, fn, tn, l1t->trx->nr);
/* only send, if FACCH is selected */
if (facch) {
@@ -406,11 +413,11 @@ static int rts_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
l1sap->u.data.link_id = link_id;
l1sap->u.data.fn = fn;
- rc = l1sap_up(l1h->trx, l1sap);
+ rc = l1sap_up(l1t->trx, l1sap);
}
/* dont send, if TCH is in signalling only mode */
- if (l1h->chan_states[tn][chan].rsl_cmode != RSL_CMOD_SPD_SIGN) {
+ if (l1ts->chan_state[chan].rsl_cmode != RSL_CMOD_SPD_SIGN) {
/* generate prim */
msg = l1sap_msgb_alloc(200);
if (!msg)
@@ -421,27 +428,27 @@ static int rts_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
l1sap->u.tch.chan_nr = chan_nr;
l1sap->u.tch.fn = fn;
- return l1sap_up(l1h->trx, l1sap);
+ return l1sap_up(l1t->trx, l1sap);
}
return rc;
}
/* RTS for full rate traffic frame */
-static int rts_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan)
{
/* TCH/F may include FACCH on every 4th burst */
- return rts_tch_common(l1h, tn, fn, chan, 1);
+ return rts_tch_common(l1t, tn, fn, chan, 1);
}
/* RTS for half rate traffic frame */
-static int rts_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan)
{
/* the FN 4/5, 13/14, 21/22 defines that FACCH may be included. */
- return rts_tch_common(l1h, tn, fn, chan, ((fn % 26) >> 2) & 1);
+ return rts_tch_common(l1t, tn, fn, chan, ((fn % 26) >> 2) & 1);
}
@@ -450,25 +457,25 @@ static int rts_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
*/
/* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */
-static ubit_t *tx_idle_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr);
return NULL;
}
-static ubit_t *tx_fcch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr);
return (ubit_t *) fcch_burst;
}
-static ubit_t *tx_sch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
static ubit_t bits[148], burst[78];
@@ -477,12 +484,12 @@ static ubit_t *tx_sch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
uint8_t t3p, bsic;
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr);
/* create SB info from GSM time and BSIC */
gsm_fn2gsmtime(&t, fn);
t3p = t.t3 / 10;
- bsic = l1h->trx->bts->bsic;
+ bsic = l1t->trx->bts->bsic;
sb_info[0] =
((bsic & 0x3f) << 2) |
((t.t1 & 0x600) >> 9);
@@ -508,16 +515,17 @@ static ubit_t *tx_sch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
return bits;
}
-static struct msgb *dequeue_prim(struct trx_l1h *l1h, int8_t tn,uint32_t fn,
+static struct msgb *dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
enum trx_chan_type chan)
{
struct msgb *msg, *msg2;
struct osmo_phsap_prim *l1sap;
uint32_t prim_fn;
uint8_t chan_nr, link_id;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
/* get prim of current fn from queue */
- llist_for_each_entry_safe(msg, msg2, &l1h->dl_prims[tn], list) {
+ llist_for_each_entry_safe(msg, msg2, &l1ts->dl_prims, list) {
l1sap = msgb_l1sap_prim(msg);
if (l1sap->oph.operation != PRIM_OP_REQUEST) {
wrong_type:
@@ -548,7 +556,7 @@ free_msg:
"is out of range, or channel already disabled. "
"If this happens in conjunction with PCU, "
"increase 'rts-advance' by 5. (current fn=%u)\n",
- l1h->trx->nr, tn, l1sap->u.data.fn, fn);
+ l1t->trx->nr, tn, l1sap->u.data.fn, fn);
/* unlink and free message */
llist_del(&msg->list);
msgb_free(msg);
@@ -578,12 +586,13 @@ found_msg:
return msg;
}
-static int compose_ph_data_ind(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t *l2, uint8_t l2_len, float rssi)
{
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
/* compose primitive */
msg = l1sap_msgb_alloc(l2_len);
@@ -599,19 +608,20 @@ static int compose_ph_data_ind(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
memcpy(msg->l2h, l2, l2_len);
if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id))
- l1h->chan_states[tn][chan].lost = 0;
+ l1ts->chan_state[chan].lost = 0;
/* forward primitive */
- l1sap_up(l1h->trx, l1sap);
+ l1sap_up(l1t->trx, l1sap);
return 0;
}
-static int compose_tch_ind(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len)
{
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
/* compose primitive */
msg = l1sap_msgb_alloc(tch_len);
@@ -624,20 +634,22 @@ static int compose_tch_ind(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if (tch_len)
memcpy(msg->l2h, tch, tch_len);
- if (l1h->chan_states[tn][chan].lost)
- l1h->chan_states[tn][chan].lost--;
+ if (l1ts->chan_state[chan].lost)
+ l1ts->chan_state[chan].lost--;
/* forward primitive */
- l1sap_up(l1h->trx, l1sap);
+ l1sap_up(l1t->trx, l1sap);
return 0;
}
-static ubit_t *tx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
struct msgb *msg = NULL; /* make GCC happy */
- ubit_t *burst, **bursts_p = &l1h->chan_states[tn][chan].dl_bursts;
+ ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
static ubit_t bits[148];
/* send burst, if we already got a frame */
@@ -648,13 +660,13 @@ static ubit_t *tx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
}
/* get mac block from queue */
- msg = dequeue_prim(l1h, tn, fn, chan);
+ msg = dequeue_prim(l1t, tn, fn, chan);
if (msg)
goto got_msg;
LOGP(DL1C, LOGL_INFO, "%s has not been served !! No prim for "
"trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1h->trx->nr, tn, fn);
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
no_msg:
/* free burst memory */
@@ -677,15 +689,15 @@ got_msg:
/* handle loss detection of sacch */
if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) {
/* count and send BFI */
- if (++(l1h->chan_states[tn][chan].lost) > 1) {
+ if (++(l1ts->chan_state[chan].lost) > 1) {
/* TODO: Should we pass old TOA here? Otherwise we risk
* unnecessary decreasing TA */
/* Send uplnk measurement information to L2 */
- l1if_process_meas_res(l1h->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
+ l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
456, 456, -110, 0);
- compose_ph_data_ind(l1h, tn, 0, chan, NULL, 0, -110);
+ compose_ph_data_ind(l1t, tn, 0, chan, NULL, 0, -110);
}
}
@@ -707,21 +719,23 @@ send_burst:
burst = *bursts_p + bid * 116;
memset(bits, 0, 3);
memcpy(bits + 3, burst, 58);
- memcpy(bits + 61, tsc[l1h->config.tsc], 26);
+ memcpy(bits + 61, tsc[gsm_ts_tsc(ts)], 26);
memcpy(bits + 87, burst + 58, 58);
memset(bits + 145, 0, 3);
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
return bits;
}
-static ubit_t *tx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
struct msgb *msg = NULL; /* make GCC happy */
- ubit_t *burst, **bursts_p = &l1h->chan_states[tn][chan].dl_bursts;
+ ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
static ubit_t bits[148];
int rc;
@@ -733,13 +747,13 @@ static ubit_t *tx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
}
/* get mac block from queue */
- msg = dequeue_prim(l1h, tn, fn, chan);
+ msg = dequeue_prim(l1t, tn, fn, chan);
if (msg)
goto got_msg;
LOGP(DL1C, LOGL_INFO, "%s has not been served !! No prim for "
"trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1h->trx->nr, tn, fn);
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
no_msg:
/* free burst memory */
@@ -777,29 +791,30 @@ send_burst:
burst = *bursts_p + bid * 116;
memset(bits, 0, 3);
memcpy(bits + 3, burst, 58);
- memcpy(bits + 61, tsc[l1h->config.tsc], 26);
+ memcpy(bits + 61, tsc[gsm_ts_tsc(ts)], 26);
memcpy(bits + 87, burst + 58, 58);
memset(bits + 145, 0, 3);
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
return bits;
}
-static void tx_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, struct msgb **_msg_tch,
struct msgb **_msg_facch, int codec_mode_request)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL;
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
uint8_t rsl_cmode = chan_state->rsl_cmode;
uint8_t tch_mode = chan_state->tch_mode;
struct osmo_phsap_prim *l1sap;
/* handle loss detection of received TCH frames */
if (rsl_cmode == RSL_CMOD_SPD_SPEECH
- && ++(l1h->chan_states[tn][chan].lost) > 5) {
+ && ++(chan_state->lost) > 5) {
uint8_t tch_data[GSM_FR_BYTES];
int len;
@@ -831,7 +846,7 @@ static void tx_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if (len < 2)
break;
memset(tch_data + 2, 0, len - 2);
- compose_tch_ind(l1h, tn, 0, chan, tch_data, len);
+ compose_tch_ind(l1t, tn, 0, chan, tch_data, len);
break;
default:
inval_mode1:
@@ -840,12 +855,12 @@ inval_mode1:
len = 0;
}
if (len)
- compose_tch_ind(l1h, tn, 0, chan, tch_data, len);
+ compose_tch_ind(l1t, tn, 0, chan, tch_data, len);
}
/* get frame and unlink from queue */
- msg1 = dequeue_prim(l1h, tn, fn, chan);
- msg2 = dequeue_prim(l1h, tn, fn, chan);
+ msg1 = dequeue_prim(l1t, tn, fn, chan);
+ msg2 = dequeue_prim(l1t, tn, fn, chan);
if (msg1) {
l1sap = msgb_l1sap_prim(msg1);
if (l1sap->oph.primitive == PRIM_TCH) {
@@ -898,7 +913,7 @@ inval_mode1:
LOGP(DL1C, LOGL_NOTICE, "%s Dropping speech frame, "
"because we are not in speech mode trx=%u "
"ts=%u at fn=%u.\n", trx_chan_desc[chan].name,
- l1h->trx->nr, tn, fn);
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
@@ -913,7 +928,7 @@ inval_mode1:
"HR frame' trx=%u ts=%u at "
"fn=%u.\n",
trx_chan_desc[chan].name,
- l1h->trx->nr, tn, fn);
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
@@ -924,7 +939,7 @@ inval_mode1:
LOGP(DL1C, LOGL_NOTICE, "%s Transmitting 'bad "
"FR frame' trx=%u ts=%u at fn=%u.\n",
trx_chan_desc[chan].name,
- l1h->trx->nr, tn, fn);
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
@@ -937,7 +952,7 @@ inval_mode1:
LOGP(DL1C, LOGL_NOTICE, "%s Transmitting 'bad "
"EFR frame' trx=%u ts=%u at fn=%u.\n",
trx_chan_desc[chan].name,
- l1h->trx->nr, tn, fn);
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
@@ -966,7 +981,7 @@ inval_mode1:
" of RTP frame not in list. "
"trx=%u ts=%u\n",
trx_chan_desc[chan].name, ft_codec,
- l1h->trx->nr, tn);
+ l1t->trx->nr, tn);
goto free_bad_msg;
}
if (codec_mode_request && chan_state->dl_ft != ft) {
@@ -974,7 +989,7 @@ inval_mode1:
" of RTP cannot be changed now, but in "
"next frame. trx=%u ts=%u\n",
trx_chan_desc[chan].name, ft_codec,
- l1h->trx->nr, tn);
+ l1t->trx->nr, tn);
goto free_bad_msg;
}
chan_state->dl_ft = ft;
@@ -982,7 +997,7 @@ inval_mode1:
LOGP(DL1C, LOGL_NOTICE, "%s Transmitting 'bad "
"AMR frame' trx=%u ts=%u at fn=%u.\n",
trx_chan_desc[chan].name,
- l1h->trx->nr, tn, fn);
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
@@ -1014,11 +1029,13 @@ send_frame:
*_msg_facch = msg_facch;
}
-static ubit_t *tx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
struct msgb *msg_tch = NULL, *msg_facch = NULL;
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
uint8_t tch_mode = chan_state->tch_mode;
ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
static ubit_t bits[148];
@@ -1030,7 +1047,7 @@ static ubit_t *tx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
goto send_burst;
}
- tx_tch_common(l1h, tn, fn, chan, bid, &msg_tch, &msg_facch,
+ tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
(((fn + 4) % 26) >> 2) & 1);
/* alloc burst memory, if not already,
@@ -1048,7 +1065,7 @@ static ubit_t *tx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if (!msg_tch && !msg_facch) {
LOGP(DL1C, LOGL_INFO, "%s has not been served !! No prim for "
"trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1h->trx->nr, tn, fn);
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
goto send_burst;
}
@@ -1079,21 +1096,23 @@ send_burst:
burst = *bursts_p + bid * 116;
memset(bits, 0, 3);
memcpy(bits + 3, burst, 58);
- memcpy(bits + 61, tsc[l1h->config.tsc], 26);
+ memcpy(bits + 61, tsc[gsm_ts_tsc(ts)], 26);
memcpy(bits + 87, burst + 58, 58);
memset(bits + 145, 0, 3);
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
return bits;
}
-static ubit_t *tx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid)
{
struct msgb *msg_tch = NULL, *msg_facch = NULL;
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
uint8_t tch_mode = chan_state->tch_mode;
ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
static ubit_t bits[148];
@@ -1106,7 +1125,7 @@ static ubit_t *tx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
}
/* get TCH and/or FACCH */
- tx_tch_common(l1h, tn, fn, chan, bid, &msg_tch, &msg_facch,
+ tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
(((fn + 4) % 26) >> 2) & 1);
/* check for FACCH alignment */
@@ -1138,7 +1157,7 @@ static ubit_t *tx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) {
LOGP(DL1C, LOGL_INFO, "%s has not been served !! No prim for "
"trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1h->trx->nr, tn, fn);
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
goto send_burst;
}
@@ -1171,12 +1190,12 @@ send_burst:
burst = *bursts_p + bid * 116;
memset(bits, 0, 3);
memcpy(bits + 3, burst, 58);
- memcpy(bits + 61, tsc[l1h->config.tsc], 26);
+ memcpy(bits + 61, tsc[gsm_ts_tsc(ts)], 26);
memcpy(bits + 87, burst + 58, 58);
memset(bits + 145, 0, 3);
LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
return bits;
}
@@ -1186,7 +1205,7 @@ send_burst:
* RX on uplink (indication to upper layer)
*/
-static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
@@ -1201,7 +1220,7 @@ static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
trx_chan_desc[chan].name, fn, toa);
/* decode */
- rc = rach_decode(&ra, bits + 8 + 41, l1h->trx->bts->bsic);
+ rc = rach_decode(&ra, bits + 8 + 41, l1t->trx->bts->bsic);
if (rc) {
LOGP(DL1C, LOGL_NOTICE, "Received bad AB frame at fn=%u "
"(%u/51)\n", fn, fn % 51);
@@ -1223,17 +1242,18 @@ static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
l1sap.u.rach_ind.fn = fn;
/* forward primitive */
- l1sap_up(l1h->trx, &l1sap);
+ l1sap_up(l1t->trx, &l1sap);
return 0;
}
/*! \brief a single burst was received by the PHY, process it */
-static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint32_t *first_fn = &chan_state->ul_first_fn;
uint8_t *mask = &chan_state->ul_mask;
@@ -1247,10 +1267,10 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
- return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
+ return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "Data received %s fn=%u ts=%u trx=%u bid=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
/* alloc burst memory, if not already */
if (!*bursts_p) {
@@ -1284,7 +1304,7 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* send burst information to loops process */
if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) {
- trx_loop_sacch_input(l1h, trx_chan_desc[chan].chan_nr | tn,
+ trx_loop_sacch_input(l1t, trx_chan_desc[chan].chan_nr | tn,
chan_state, rssi, toa);
}
@@ -1296,7 +1316,7 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if ((*mask & 0xf) != 0xf) {
LOGP(DL1C, LOGL_NOTICE, "Received incomplete data frame at "
"fn=%u (%u/%u) for %s\n", *first_fn,
- (*first_fn) % l1h->mf_period[tn], l1h->mf_period[tn],
+ (*first_fn) % l1ts->mf_period, l1ts->mf_period,
trx_chan_desc[chan].name);
/* we require first burst to have correct FN */
@@ -1312,24 +1332,25 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if (rc) {
LOGP(DL1C, LOGL_NOTICE, "Received bad data frame at fn=%u "
"(%u/%u) for %s\n", *first_fn,
- (*first_fn) % l1h->mf_period[tn], l1h->mf_period[tn],
+ (*first_fn) % l1ts->mf_period, l1ts->mf_period,
trx_chan_desc[chan].name);
l2_len = 0;
} else
l2_len = GSM_MACBLOCK_LEN;
/* Send uplnk measurement information to L2 */
- l1if_process_meas_res(l1h->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
+ l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
n_errors, n_bits_total, *rssi_sum / *rssi_num, *toa_sum / *toa_num);
- return compose_ph_data_ind(l1h, tn, *first_fn, chan, l2, l2_len, *rssi_sum / *rssi_num);
+ return compose_ph_data_ind(l1t, tn, *first_fn, chan, l2, l2_len, *rssi_sum / *rssi_num);
}
-static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint8_t *mask = &chan_state->ul_mask;
float *rssi_sum = &chan_state->rssi_sum;
@@ -1341,7 +1362,7 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
int rc;
LOGP(DL1C, LOGL_DEBUG, "PDTCH received %s fn=%u ts=%u trx=%u bid=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
/* alloc burst memory, if not already */
if (!*bursts_p) {
@@ -1380,7 +1401,7 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if ((*mask & 0xf) != 0xf) {
LOGP(DL1C, LOGL_NOTICE, "Received incomplete PDTCH block "
"ending at fn=%u (%u/%u) for %s\n", fn,
- fn % l1h->mf_period[tn], l1h->mf_period[tn],
+ fn % l1ts->mf_period, l1ts->mf_period,
trx_chan_desc[chan].name);
}
*mask = 0x0;
@@ -1389,27 +1410,28 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
rc = pdtch_decode(l2 + 1, *bursts_p, NULL, &n_errors, &n_bits_total);
/* Send uplnk measurement information to L2 */
- l1if_process_meas_res(l1h->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
+ l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
n_errors, n_bits_total, *rssi_sum / *rssi_num, *toa_sum / *toa_num);
if (rc <= 0) {
LOGP(DL1C, LOGL_NOTICE, "Received bad PDTCH block ending at "
- "fn=%u (%u/%u) for %s\n", fn, fn % l1h->mf_period[tn],
- l1h->mf_period[tn], trx_chan_desc[chan].name);
+ "fn=%u (%u/%u) for %s\n", fn, fn % l1ts->mf_period,
+ l1ts->mf_period, trx_chan_desc[chan].name);
return 0;
}
l2[0] = 7; /* valid frame */
- return compose_ph_data_ind(l1h, tn, (fn + GSM_HYPERFRAME - 3) % GSM_HYPERFRAME, chan,
+ return compose_ph_data_ind(l1t, tn, (fn + GSM_HYPERFRAME - 3) % GSM_HYPERFRAME, chan,
l2, rc + 1, *rssi_sum / *rssi_num);
}
-static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint8_t *mask = &chan_state->ul_mask;
uint8_t rsl_cmode = chan_state->rsl_cmode;
@@ -1420,10 +1442,10 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
- return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
+ return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "TCH/F received %s fn=%u ts=%u trx=%u bid=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
/* alloc burst memory, if not already */
if (!*bursts_p) {
@@ -1454,7 +1476,7 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if ((*mask & 0xf) != 0xf) {
LOGP(DL1C, LOGL_NOTICE, "Received incomplete TCH frame ending "
"at fn=%u (%u/%u) for %s\n", fn,
- fn % l1h->mf_period[tn], l1h->mf_period[tn],
+ fn % l1ts->mf_period, l1ts->mf_period,
trx_chan_desc[chan].name);
}
*mask = 0x0;
@@ -1479,7 +1501,7 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
chan_state->codecs, &chan_state->ul_ft,
&chan_state->ul_cmr, &n_errors, &n_bits_total);
if (rc)
- trx_loop_amr_input(l1h,
+ trx_loop_amr_input(l1t,
trx_chan_desc[chan].chan_nr | tn, chan_state,
(float)n_errors/(float)n_bits_total);
amr = 2; /* we store tch_data + 2 header bytes */
@@ -1498,7 +1520,7 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
memcpy(*bursts_p, *bursts_p + 464, 464);
/* Send uplnk measurement information to L2 */
- l1if_process_meas_res(l1h->trx, tn, fn, trx_chan_desc[chan].chan_nr|tn,
+ l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr|tn,
n_errors, n_bits_total, rssi, toa);
/* Check if the frame is bad */
@@ -1516,7 +1538,7 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* FACCH */
if (rc == GSM_MACBLOCK_LEN) {
- compose_ph_data_ind(l1h, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
+ compose_ph_data_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
tch_data + amr, GSM_MACBLOCK_LEN, rssi);
bfi:
if (rsl_cmode == RSL_CMOD_SPD_SPEECH) {
@@ -1551,15 +1573,16 @@ bfi:
return 0;
/* TCH or BFI */
- return compose_tch_ind(l1h, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
+ return compose_tch_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
tch_data, rc);
}
-static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+static int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
- struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan];
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint8_t *mask = &chan_state->ul_mask;
uint8_t rsl_cmode = chan_state->rsl_cmode;
@@ -1570,10 +1593,10 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
- return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
+ return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "TCH/H received %s fn=%u ts=%u trx=%u bid=%u\n",
- trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
+ trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
/* alloc burst memory, if not already */
if (!*bursts_p) {
@@ -1604,7 +1627,7 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
if ((*mask & 0x3) != 0x3) {
LOGP(DL1C, LOGL_NOTICE, "Received incomplete TCH frame ending "
"at fn=%u (%u/%u) for %s\n", fn,
- fn % l1h->mf_period[tn], l1h->mf_period[tn],
+ fn % l1ts->mf_period, l1ts->mf_period,
trx_chan_desc[chan].name);
}
*mask = 0x0;
@@ -1641,7 +1664,7 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
chan_state->codecs, &chan_state->ul_ft,
&chan_state->ul_cmr, &n_errors, &n_bits_total);
if (rc)
- trx_loop_amr_input(l1h,
+ trx_loop_amr_input(l1t,
trx_chan_desc[chan].chan_nr | tn, chan_state,
(float)n_errors/(float)n_bits_total);
amr = 2; /* we store tch_data + 2 two */
@@ -1661,7 +1684,7 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
memcpy(*bursts_p + 232, *bursts_p + 464, 232);
/* Send uplnk measurement information to L2 */
- l1if_process_meas_res(l1h->trx, tn, fn, trx_chan_desc[chan].chan_nr|tn,
+ l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr|tn,
n_errors, n_bits_total, rssi, toa);
/* Check if the frame is bad */
@@ -1680,7 +1703,7 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
/* FACCH */
if (rc == GSM_MACBLOCK_LEN) {
chan_state->ul_ongoing_facch = 1;
- compose_ph_data_ind(l1h, tn,
+ compose_ph_data_ind(l1t, tn,
(fn + GSM_HYPERFRAME - 10 - ((fn % 26) >= 19)) % GSM_HYPERFRAME, chan,
tch_data + amr, GSM_MACBLOCK_LEN, rssi);
bfi:
@@ -1718,7 +1741,7 @@ bfi:
* with the slot 12, so an extra FN must be substracted to get correct
* start of frame.
*/
- return compose_tch_ind(l1h, tn,
+ return compose_tch_ind(l1t, tn,
(fn + GSM_HYPERFRAME - 10 - ((fn%26)==19) - ((fn%26)==20)) % GSM_HYPERFRAME,
chan, tch_data, rc);
}
@@ -2487,61 +2510,59 @@ static const struct trx_sched_multiframe trx_sched_multiframes[] = {
*/
/* set multiframe scheduler to given pchan */
-int trx_sched_set_pchan(struct trx_l1h *l1h, uint8_t tn,
+int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
enum gsm_phys_chan_config pchan)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
int i;
- /* ignore disabled slots */
- if (!(l1h->config.slotmask & (1 << tn)))
- return -ENOTSUP;
-
for (i = 0; i < ARRAY_SIZE(trx_sched_multiframes); i++) {
if (trx_sched_multiframes[i].pchan == pchan
&& (trx_sched_multiframes[i].slotmask & (1 << tn))) {
- l1h->mf_index[tn] = i;
- l1h->mf_period[tn] = trx_sched_multiframes[i].period;
- l1h->mf_frames[tn] = trx_sched_multiframes[i].frames;
+ l1ts->mf_index = i;
+ l1ts->mf_period = trx_sched_multiframes[i].period;
+ l1ts->mf_frames = trx_sched_multiframes[i].frames;
LOGP(DL1C, LOGL_NOTICE, "Configuring multiframe with "
"%s trx=%d ts=%d\n",
trx_sched_multiframes[i].name,
- l1h->trx->nr, tn);
+ l1t->trx->nr, tn);
return 0;
}
}
LOGP(DL1C, LOGL_NOTICE, "Failed to configuring multiframe "
- "trx=%d ts=%d\n", l1h->trx->nr, tn);
+ "trx=%d ts=%d\n", l1t->trx->nr, tn);
return -ENOTSUP;
}
/* setting all logical channels given attributes to active/inactive */
-int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
+int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
int active)
{
uint8_t tn = L1SAP_CHAN2TS(chan_nr);
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
uint8_t ss = l1sap_chan2ss(chan_nr);
int i;
int rc = -EINVAL;
- struct trx_chan_state *chan_state;
/* look for all matching chan_nr/link_id */
for (i = 0; i < _TRX_CHAN_MAX; i++) {
+ struct l1sched_chan_state *chan_state;
+ chan_state = &l1ts->chan_state[i];
/* skip if pchan type does not match pdch flag */
- if ((trx_sched_multiframes[l1h->mf_index[tn]].pchan
+ if ((trx_sched_multiframes[l1ts->mf_index].pchan
== GSM_PCHAN_PDCH)
!= trx_chan_desc[i].pdch)
continue;
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
&& trx_chan_desc[i].link_id == link_id) {
- chan_state = &l1h->chan_states[tn][i];
rc = 0;
if (chan_state->active == active)
continue;
LOGP(DL1C, LOGL_NOTICE, "%s %s on trx=%d ts=%d\n",
(active) ? "Activating" : "Deactivating",
- trx_chan_desc[i].name, l1h->trx->nr, tn);
+ trx_chan_desc[i].name, l1t->trx->nr, tn);
if (active)
memset(chan_state, 0, sizeof(*chan_state));
chan_state->active = active;
@@ -2554,12 +2575,14 @@ int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
talloc_free(chan_state->ul_bursts);
chan_state->ul_bursts = NULL;
}
+ if (!active)
+ chan_state->ho_rach_detect = 0;
}
}
/* disable handover detection (on deactivation) */
- if (l1h->ho_rach_detect[tn][ss]) {
- l1h->ho_rach_detect[tn][ss] = 0;
+ if (!active) {
+ struct trx_l1h *l1h = trx_l1h_hdl(l1t->trx);
trx_if_cmd_nohandover(l1h, tn, ss);
}
@@ -2567,28 +2590,30 @@ int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
}
/* setting all logical channels given attributes to active/inactive */
-int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
+int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
uint8_t codec2, uint8_t codec3, uint8_t initial_id, uint8_t handover)
{
uint8_t tn = L1SAP_CHAN2TS(chan_nr);
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct trx_l1h *l1h = trx_l1h_hdl(l1t->trx);
uint8_t ss = l1sap_chan2ss(chan_nr);
int i;
int rc = -EINVAL;
- struct trx_chan_state *chan_state;
+ struct l1sched_chan_state *chan_state;
/* no mode for PDCH */
- if (trx_sched_multiframes[l1h->mf_index[tn]].pchan == GSM_PCHAN_PDCH)
+ if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH)
return 0;
/* look for all matching chan_nr/link_id */
for (i = 0; i < _TRX_CHAN_MAX; i++) {
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
&& trx_chan_desc[i].link_id == 0x00) {
- chan_state = &l1h->chan_states[tn][i];
+ chan_state = &l1ts->chan_state[i];
LOGP(DL1C, LOGL_NOTICE, "Set mode %u, %u, handover %u "
"on %s of trx=%d ts=%d\n", rsl_cmode, tch_mode,
- handover, trx_chan_desc[i].name, l1h->trx->nr,
+ handover, trx_chan_desc[i].name, l1t->trx->nr,
tn);
chan_state->rsl_cmode = rsl_cmode;
chan_state->tch_mode = tch_mode;
@@ -2617,10 +2642,8 @@ int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
* disable handover, if state is still set, since we might not know
* the actual state of transceiver (due to loss of link) */
if (handover) {
- l1h->ho_rach_detect[tn][ss] = 1;
trx_if_cmd_handover(l1h, tn, ss);
- } else if (l1h->ho_rach_detect[tn][ss]) {
- l1h->ho_rach_detect[tn][ss] = 0;
+ } else {
trx_if_cmd_nohandover(l1h, tn, ss);
}
@@ -2628,16 +2651,17 @@ int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
}
/* setting cipher on logical channels */
-int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,
+int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
int algo, uint8_t *key, int key_len)
{
uint8_t tn = L1SAP_CHAN2TS(chan_nr);
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
int i;
int rc = -EINVAL;
- struct trx_chan_state *chan_state;
+ struct l1sched_chan_state *chan_state;
/* no cipher for PDCH */
- if (trx_sched_multiframes[l1h->mf_index[tn]].pchan == GSM_PCHAN_PDCH)
+ if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH)
return 0;
/* no algorithm given means a5/0 */
@@ -2655,11 +2679,11 @@ int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,
if (trx_chan_desc[i].pdch)
continue;
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)) {
- chan_state = &l1h->chan_states[tn][i];
+ chan_state = &l1ts->chan_state[i];
LOGP(DL1C, LOGL_NOTICE, "Set a5/%d %s for %s on trx=%d "
"ts=%d\n", algo,
(downlink) ? "downlink" : "uplink",
- trx_chan_desc[i].name, l1h->trx->nr, tn);
+ trx_chan_desc[i].name, l1t->trx->nr, tn);
if (downlink) {
chan_state->dl_encr_algo = algo;
memcpy(chan_state->dl_encr_key, key, key_len);
@@ -2677,21 +2701,22 @@ int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,
}
/* process ready-to-send */
-static int trx_sched_rts(struct trx_l1h *l1h, uint8_t tn, uint32_t fn)
+static int trx_sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
const struct trx_sched_frame *frame;
uint8_t offset, period, bid;
trx_sched_rts_func *func;
enum trx_chan_type chan;
/* no multiframe set */
- if (!l1h->mf_index[tn])
+ if (!l1ts->mf_index)
return 0;
/* get frame from multiframe */
- period = l1h->mf_period[tn];
+ period = l1ts->mf_period;
offset = fn % period;
- frame = l1h->mf_frames[tn] + offset;
+ frame = l1ts->mf_frames + offset;
chan = frame->dl_chan;
bid = frame->dl_bid;
@@ -2707,49 +2732,51 @@ static int trx_sched_rts(struct trx_l1h *l1h, uint8_t tn, uint32_t fn)
/* check if channel is active */
if (!trx_chan_desc[chan].auto_active
- && !l1h->chan_states[tn][chan].active)
+ && !l1ts->chan_state[chan].active)
return -EINVAL;
- return func(l1h, tn, fn, frame->dl_chan);
+ return func(l1t, tn, fn, frame->dl_chan);
}
/* process downlink burst */
-static const ubit_t *trx_sched_dl_burst(struct trx_l1h *l1h, uint8_t tn,
+static const ubit_t *trx_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
uint32_t fn)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *l1cs;
const struct trx_sched_frame *frame;
uint8_t offset, period, bid;
trx_sched_dl_func *func;
enum trx_chan_type chan;
ubit_t *bits = NULL;
- if (!l1h->mf_index[tn])
+ if (!l1ts->mf_index)
goto no_data;
/* get frame from multiframe */
- period = l1h->mf_period[tn];
+ period = l1ts->mf_period;
offset = fn % period;
- frame = l1h->mf_frames[tn] + offset;
+ frame = l1ts->mf_frames + offset;
chan = frame->dl_chan;
bid = frame->dl_bid;
func = trx_chan_desc[chan].dl_fn;
+ l1cs = &l1ts->chan_state[chan];
+
/* check if channel is active */
- if (!trx_chan_desc[chan].auto_active
- && !l1h->chan_states[tn][chan].active)
+ if (!trx_chan_desc[chan].auto_active && !l1cs->active)
goto no_data;
/* get burst from function */
- bits = func(l1h, tn, fn, chan, bid);
+ bits = func(l1t, tn, fn, chan, bid);
/* encrypt */
- if (bits && l1h->chan_states[tn][chan].dl_encr_algo) {
+ if (bits && l1cs->dl_encr_algo) {
ubit_t ks[114];
int i;
- osmo_a5(l1h->chan_states[tn][chan].dl_encr_algo,
- l1h->chan_states[tn][chan].dl_encr_key, fn, ks, NULL);
+ osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, fn, ks, NULL);
for (i = 0; i < 57; i++) {
bits[i + 3] ^= ks[i];
bits[i + 88] ^= ks[i + 57];
@@ -2758,7 +2785,7 @@ static const ubit_t *trx_sched_dl_burst(struct trx_l1h *l1h, uint8_t tn,
no_data:
/* in case of C0, we need a dummy burst to maintain RF power */
- if (bits == NULL && l1h->trx == l1h->trx->bts->c0) {
+ if (bits == NULL && l1t->trx == l1t->trx->bts->c0) {
if (0) if (chan != TRXC_IDLE) // hack
LOGP(DL1C, LOGL_DEBUG, "No burst data for %s fn=%u ts=%u "
"burst=%d on C0, so filling with dummy burst\n",
@@ -2770,41 +2797,44 @@ if (0) if (chan != TRXC_IDLE) // hack
}
/* process uplink burst */
-int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t current_fn,
+int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t current_fn,
sbit_t *bits, int8_t rssi, float toa)
{
+ struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+ struct l1sched_chan_state *l1cs;
const struct trx_sched_frame *frame;
uint8_t offset, period, bid;
trx_sched_ul_func *func;
enum trx_chan_type chan;
uint32_t fn, elapsed;
- if (!l1h->mf_index[tn])
+ if (!l1ts->mf_index)
return -EINVAL;
/* calculate how many frames have been elapsed */
- elapsed = (current_fn + GSM_HYPERFRAME - l1h->mf_last_fn[tn]) % GSM_HYPERFRAME;
+ elapsed = (current_fn + GSM_HYPERFRAME - l1ts->mf_last_fn) % GSM_HYPERFRAME;
/* start counting from last fn + 1, but only if not too many fn have
* been elapsed */
if (elapsed < 10)
- fn = (l1h->mf_last_fn[tn] + 1) % GSM_HYPERFRAME;
+ fn = (l1ts->mf_last_fn + 1) % GSM_HYPERFRAME;
else
fn = current_fn;
while (42) {
/* get frame from multiframe */
- period = l1h->mf_period[tn];
+ period = l1ts->mf_period;
offset = fn % period;
- frame = l1h->mf_frames[tn] + offset;
+ frame = l1ts->mf_frames + offset;
chan = frame->ul_chan;
bid = frame->ul_bid;
func = trx_chan_desc[chan].ul_fn;
+ l1cs = &l1ts->chan_state[chan];
+
/* check if channel is active */
- if (!trx_chan_desc[chan].auto_active
- && !l1h->chan_states[tn][chan].active)
+ if (!trx_chan_desc[chan].auto_active && !l1cs->active)
goto next_frame;
/* omit bursts which have no handler, like IDLE bursts */
@@ -2814,12 +2844,12 @@ int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t current_fn,
/* put burst to function */
if (fn == current_fn) {
/* decrypt */
- if (bits && l1h->chan_states[tn][chan].ul_encr_algo) {
+ if (bits && l1cs->ul_encr_algo) {
ubit_t ks[114];
int i;
- osmo_a5(l1h->chan_states[tn][chan].ul_encr_algo,
- l1h->chan_states[tn][chan].ul_encr_key,
+ osmo_a5(l1cs->ul_encr_algo,
+ l1cs->ul_encr_key,
fn, NULL, ks);
for (i = 0; i < 57; i++) {
if (ks[i])
@@ -2829,13 +2859,12 @@ int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t current_fn,
}
}
- func(l1h, tn, fn, chan, bid, bits, rssi, toa);
- } else if (chan != TRXC_RACH
- && !l1h->chan_states[tn][chan].ho_rach_detect) {
+ func(l1t, tn, fn, chan, bid, bits, rssi, toa);
+ } else if (chan != TRXC_RACH && !l1cs->ho_rach_detect) {
sbit_t spare[148];
memset(spare, 0, 148);
- func(l1h, tn, fn, chan, bid, spare, -128, 0);
+ func(l1t, tn, fn, chan, bid, spare, -128, 0);
}
next_frame:
@@ -2846,7 +2875,7 @@ next_frame:
fn = (fn + 1) % GSM_HYPERFRAME;
}
- l1h->mf_last_fn[tn] = fn;
+ l1ts->mf_last_fn = fn;
return 0;
}
@@ -2855,7 +2884,6 @@ next_frame:
static int trx_sched_fn(uint32_t fn)
{
struct gsm_bts_trx *trx;
- struct trx_l1h *l1h;
uint8_t tn;
const ubit_t *bits;
uint8_t gain;
@@ -2869,22 +2897,20 @@ static int trx_sched_fn(uint32_t fn)
/* process every TRX */
llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx_l1h_hdl(trx);
+ struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct l1sched_trx *l1t = trx_l1sched_hdl(trx);
/* we don't schedule, if power is off */
if (!l1h->config.poweron)
continue;
/* process every TS of TRX */
- for (tn = 0; tn < TRX_NR_TS; tn++) {
- /* ignore disabled slots */
- if (!(l1h->config.slotmask & (1 << tn)))
- continue;
+ for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
/* ready-to-send */
- trx_sched_rts(l1h, tn,
+ trx_sched_rts(l1t, tn,
(fn + trx_rts_advance) % GSM_HYPERFRAME);
/* get burst for FN */
- bits = trx_sched_dl_burst(l1h, tn, fn);
+ bits = trx_sched_dl_burst(l1t, tn, fn);
if (!bits) {
/* if no bits, send no burst */
continue;
@@ -2910,6 +2936,7 @@ extern int quit;
/* this timer fires for every FN to be processed */
static void trx_ctrl_timer_cb(void *data)
{
+ struct gsm_bts *bts = data;
struct timeval tv_now, *tv_clock = &transceiver_clock_tv;
int32_t elapsed;
@@ -2926,7 +2953,7 @@ no_clock:
/* close all logical channels and reset timeslots */
llist_for_each_entry(trx, &bts->trx_list, list) {
trx_if_flush(trx_l1h_hdl(trx));
- trx_sched_reset(trx_l1h_hdl(trx));
+ trx_sched_reset(trx_l1sched_hdl(trx));
if (trx->nr == 0)
trx_if_cmd_poweroff(trx_l1h_hdl(trx));
}
@@ -3061,3 +3088,8 @@ new_clock:
return 0;
}
+struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn)
+{
+ OSMO_ASSERT(tn < ARRAY_SIZE(l1t->ts));
+ return &l1t->ts[tn];
+}
diff --git a/src/osmo-bts-trx/scheduler.h b/src/osmo-bts-trx/scheduler.h
index 3e30693..c153b9e 100644
--- a/src/osmo-bts-trx/scheduler.h
+++ b/src/osmo-bts-trx/scheduler.h
@@ -1,6 +1,129 @@
#ifndef TRX_SCHEDULER_H
#define TRX_SCHEDULER_H
+/* These types define the different channels on a multiframe.
+ * Each channel has queues and can be activated individually.
+ */
+enum trx_chan_type {
+ TRXC_IDLE = 0,
+ TRXC_FCCH,
+ TRXC_SCH,
+ TRXC_BCCH,
+ TRXC_RACH,
+ TRXC_CCCH,
+ TRXC_TCHF,
+ TRXC_TCHH_0,
+ TRXC_TCHH_1,
+ TRXC_SDCCH4_0,
+ TRXC_SDCCH4_1,
+ TRXC_SDCCH4_2,
+ TRXC_SDCCH4_3,
+ TRXC_SDCCH8_0,
+ TRXC_SDCCH8_1,
+ TRXC_SDCCH8_2,
+ TRXC_SDCCH8_3,
+ TRXC_SDCCH8_4,
+ TRXC_SDCCH8_5,
+ TRXC_SDCCH8_6,
+ TRXC_SDCCH8_7,
+ TRXC_SACCHTF,
+ TRXC_SACCHTH_0,
+ TRXC_SACCHTH_1,
+ TRXC_SACCH4_0,
+ TRXC_SACCH4_1,
+ TRXC_SACCH4_2,
+ TRXC_SACCH4_3,
+ TRXC_SACCH8_0,
+ TRXC_SACCH8_1,
+ TRXC_SACCH8_2,
+ TRXC_SACCH8_3,
+ TRXC_SACCH8_4,
+ TRXC_SACCH8_5,
+ TRXC_SACCH8_6,
+ TRXC_SACCH8_7,
+ TRXC_PDTCH,
+ TRXC_PTCCH,
+ _TRX_CHAN_MAX
+};
+
+/* States each channel on a multiframe */
+struct l1sched_chan_state {
+ /* scheduler */
+ uint8_t active; /* Channel is active */
+ ubit_t *dl_bursts; /* burst buffer for TX */
+ sbit_t *ul_bursts; /* burst buffer for RX */
+ uint32_t ul_first_fn; /* fn of first burst */
+ uint8_t ul_mask; /* mask of received bursts */
+
+ /* RSSI / TOA */
+ uint8_t rssi_num; /* number of RSSI values */
+ float rssi_sum; /* sum of RSSI values */
+ uint8_t toa_num; /* number of TOA values */
+ float toa_sum; /* sum of TOA values */
+
+ /* loss detection */
+ uint8_t lost; /* (SACCH) loss detection */
+
+ /* mode */
+ uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
+
+ /* AMR */
+ uint8_t codec[4]; /* 4 possible codecs for amr */
+ int codecs; /* number of possible codecs */
+ float ber_sum; /* sum of bit error rates */
+ int ber_num; /* number of bit error rates */
+ uint8_t ul_ft; /* current uplink FT index */
+ uint8_t dl_ft; /* current downlink FT index */
+ uint8_t ul_cmr; /* current uplink CMR index */
+ uint8_t dl_cmr; /* current downlink CMR index */
+ uint8_t amr_loop; /* if AMR loop is enabled */
+
+ /* TCH/H */
+ uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
+ uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
+
+ /* encryption */
+ int ul_encr_algo; /* A5/x encry algo downlink */
+ int dl_encr_algo; /* A5/x encry algo uplink */
+ int ul_encr_key_len;
+ int dl_encr_key_len;
+ uint8_t ul_encr_key[MAX_A5_KEY_LEN];
+ uint8_t dl_encr_key[MAX_A5_KEY_LEN];
+
+ /* measurements */
+ struct {
+ uint8_t clock; /* cyclic clock counter */
+ int8_t rssi[32]; /* last RSSI values */
+ int rssi_count; /* received RSSI values */
+ int rssi_valid_count; /* number of stored value */
+ int rssi_got_burst; /* any burst received so far */
+ float toa_sum; /* sum of TOA values */
+ int toa_num; /* number of TOA value */
+ } meas;
+
+ /* handover */
+ uint8_t ho_rach_detect; /* if rach detection is on */
+};
+
+struct l1sched_ts {
+ uint8_t mf_index; /* selected multiframe index */
+ uint32_t mf_last_fn; /* last received frame number */
+ uint8_t mf_period; /* period of multiframe */
+ const struct trx_sched_frame *mf_frames; /* pointer to frame layout */
+
+ struct llist_head dl_prims; /* Queue primitves for TX */
+
+ /* Channel states for all logical channels */
+ struct l1sched_chan_state chan_state[_TRX_CHAN_MAX];
+};
+
+struct l1sched_trx {
+ struct gsm_bts_trx *trx;
+ struct l1sched_ts ts[TRX_NR_TS];
+};
+
+struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn);
+
/*! \brief how many frame numbers in advance we should send bursts to PHY */
extern uint32_t trx_clock_advance;
/*! \brief advance RTS.ind to L2 by that many clocks */
@@ -10,43 +133,43 @@ extern uint32_t transceiver_last_fn;
/*! \brief Initialize the scheudler data structures */
-int trx_sched_init(struct trx_l1h *l1h);
+int trx_sched_init(struct l1sched_trx *l1t);
/*! \brief De-initialize the scheudler data structures */
-void trx_sched_exit(struct trx_l1h *l1h);
+void trx_sched_exit(struct l1sched_trx *l1t);
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
-int trx_sched_ph_data_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap);
+int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
-int trx_sched_tch_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap);
+int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
/*! \brief PHY informs us of new (current) GSM freme nunmber */
int trx_sched_clock(uint32_t fn);
/*! \brief handle an UL burst received by PHY */
-int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
+int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
sbit_t *bits, int8_t rssi, float toa);
/*! \brief set multiframe scheduler to given physical channel config */
-int trx_sched_set_pchan(struct trx_l1h *l1h, uint8_t tn,
+int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
enum gsm_phys_chan_config pchan);
/*! \brief set all matching logical channels active/inactive */
-int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
+int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
int active);
/*! \brief set mode of all matching logical channels to given mode(s) */
-int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
+int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
uint8_t handover);
/*! \brief set ciphering on given logical channels */
-int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,
+int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
int algo, uint8_t *key, int key_len);
/* \brief close all logical channels and reset timeslots */
-void trx_sched_reset(struct trx_l1h *l1h);
+void trx_sched_reset(struct l1sched_trx *l1t);
#endif /* TRX_SCHEDULER_H */
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index 419fea6..fef2064 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -454,7 +454,7 @@ static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
fprintf(stderr, "%s\n", deb);
#endif
- trx_sched_ul_burst(l1h, tn, fn, bits, rssi, toa);
+ trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, rssi, toa);
return 0;
}
--
2.7.0
1
6
From: Max <msuraev(a)sysmocom.de>
This is v2 of patchset to simplify new hardware support by restructuring sources,
simplifying internal API and cleaining up various bits and pieces.
Max (4):
Cleanup build
Rename define for direct hw access
Restructure sources
Change internal API for consistency
.gitignore | 3 +-
configure.ac | 2 +-
src/Makefile.am | 51 +++++++++++++++++++--------------
src/{ => osmo-bts-sysmo}/femtobts.c | 0
src/{ => osmo-bts-sysmo}/femtobts.h | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_fwd.c | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_hw.c | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_if.c | 8 +++---
src/{ => osmo-bts-sysmo}/sysmo_l1_if.h | 2 +-
src/osmobts_sock.cpp | 2 +-
src/pcu_l1_if.cpp | 17 ++++++-----
11 files changed, 47 insertions(+), 38 deletions(-)
rename src/{ => osmo-bts-sysmo}/femtobts.c (100%)
rename src/{ => osmo-bts-sysmo}/femtobts.h (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_fwd.c (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_hw.c (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_if.c (98%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_if.h (98%)
--
2.5.0
1
4
From: Max <msuraev(a)sysmocom.de>
This small patchset enables future hardware support by restructuring sources and
cleaning up few bits here and there.
Max (3):
Cleanup build
Rename define for direct hw access
Restructure sources
.gitignore | 2 ++
configure.ac | 2 +-
src/Makefile.am | 51 +++++++++++++++++++--------------
src/{ => osmo-bts-sysmo}/femtobts.c | 0
src/{ => osmo-bts-sysmo}/femtobts.h | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_fwd.c | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_hw.c | 4 +--
src/{ => osmo-bts-sysmo}/sysmo_l1_if.c | 0
src/{ => osmo-bts-sysmo}/sysmo_l1_if.h | 0
src/osmobts_sock.cpp | 2 +-
src/pcu_l1_if.cpp | 6 ++--
11 files changed, 39 insertions(+), 28 deletions(-)
rename src/{ => osmo-bts-sysmo}/femtobts.c (100%)
rename src/{ => osmo-bts-sysmo}/femtobts.h (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_fwd.c (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_hw.c (97%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_if.c (100%)
rename src/{ => osmo-bts-sysmo}/sysmo_l1_if.h (100%)
--
2.5.0
3
7
Is this a proper way to copyright OsmoCSCN? I'm trying to mention both the
facts that it's something new as well as that it is based on a copy-paste of
OsmoNITB:
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info(a)sysmocom.de>
* All Rights Reserved
*
* Based on OsmoNITB:
* (C) 2008-2010 by Harald Welte <laforge(a)gnumonks.org>
* (C) 2009-2012 by Holger Hans Peter Freyther <zecke(a)selfish.org>
* All Rights Reserved
[...]
Thanks!
~Neels
--
- Neels Hofmeyr <nhofmeyr(a)sysmocom.de> http://www.sysmocom.de/
=======================================================================
* sysmocom - systems for mobile communications GmbH
* Alt-Moabit 93
* 10559 Berlin, Germany
* Sitz / Registered office: Berlin, HRB 134158 B
* Geschäftsführer / Managing Directors: Holger Freyther, Harald Welte
2
1
I'm using LCR as a GSM <-> SIP interface and I've been trying to figure out
why MO calls result in a segfault. I am running openbsc on cdc548cb and LCR
on c14326641a built and run on an ubuntu 14.04 64bit.
>From what I've investigated so far, the request_uri passed to sofia-sip is
malformed.
Has anyone seen this problem before? Would appreciate pointers.
Here are the full logs and stack trace:
** LCR Version 1.14
> 000000 DEBUG (in route.c/getrulesetbyname() line 1928): ruleset main found.
> 000000 DEBUG (in sip.cpp/sip_init() line 1997): SIP globals initialized
> 000000 DEBUG (in gsm.cpp/mncc_socket_retry_cb() line 1443): Connected to
> MNCC socket /tmp/bsc_mncc!
> su_port_create(0x6ad410): epoll_create() => 0: OK
> su_socket_port_init(0x6ad410, 0x7ffff7dcf880) called
> su_pthread_port_init(0x6ad410, 0x7ffff7dcf880) called
> nua: nua_create: entering
> [New Thread 0x7ffff6c52700 (LWP 11520)]
> su_port_create(0x7ffff00008c0): epoll_create() => 0: OK
> su_socket_port_init(0x7ffff00008c0, 0x7ffff7dcf880) called
> su_pthread_port_init(0x7ffff00008c0, 0x7ffff7dcf880) called
> nua: nua_stack_init: entering
> nua: nua_stack_set_params: entering
> soa_create("default", 0x7ffff0001130, 0x7ffff0001230) called
> soa_set_params(static::0x7ffff0001920, ...) called
> soa_set_params(static::0x7ffff0001920, ...) called
> nta_agent_create: initialized hash tables
> nta_agent_create: initialized transports
> nta_agent_create: initialized random identifiers
> nta_agent_create: initialized timer
> nta_agent_create: initialized resolver
> tport_create(): 0x7ffff0003df0
> nta: master transport created
> tport_bind_server(0x7ffff0003df0) to */127.0.0.1:5062/sip
> tport_bind_server(0x7ffff0003df0): calling tport_listen for udp
> tport_alloc_primary(0x7ffff0003df0): new primary tport 0x7ffff0004470
> tport_listen(0x7ffff0004470): listening at udp/127.0.0.1:5062/sip
> tport_bind_server(0x7ffff0003df0): calling tport_listen for tcp
> tport_alloc_primary(0x7ffff0003df0): new primary tport 0x7ffff0004910
> tport_listen(0x7ffff0004910): listening at tcp/127.0.0.1:5062/sip
> nta: bound to (127.0.0.1:5062;transport=*)
> nta: agent_init_via: SIP/2.0/udp 127.0.0.1:5062 (sip)
> nta: agent_init_via: SIP/2.0/tcp 127.0.0.1:5062 (sip)
> nta: Via fields initialized
> nta: Contact header created
> nua_register: Adding contact URL '127.0.0.1' to list.
> nua: nua_set_params: entering
> nua((nil)): sent signal r_set_params
> 000000 DEBUG (in sip.cpp/sip_init_inst() line 1942): SIP interface created
> (inst=0x6acce0)
> nua((nil)): recv signal r_set_params
> nua: nua_stack_set_params: entering
> soa_set_params(static::0x7ffff0001920, ...) called
> nua((nil)): event r_set_params 200 OK
> LCR 1.14 started, waiting for calls...
> 000000 TRACE 15.01.16 11:36:21.011 --: LCR 1.14 started, waiting for
> calls...
> nua: nua_application_event: entering
> 000000 DEBUG (in sip.cpp/sip_callback() line 1785): Event 23 from stack
> received (handle=(nil))
> 000000 DEBUG (in port.cpp/Port() line 210): new port (1) of type 0x3101,
> name 'gsm-0-in' interface 'gsm'
> 000000 DEBUG (in gsm.cpp/Pgsm() line 239): Created new GSMPort(gsm-0-in).
> 000000 DEBUG (in gsm_bs.cpp/Pgsm_bs() line 56): Created new
> GSMBSPort(gsm-0-in).
> 000000 TRACE 15.01.16 11:37:28.210 CH(1): New call ref LCR<->BSC callref
> new=0x8000000d
> 000000 TRACE 15.01.16 11:37:28.210 CH(1): Codec negotiation LCR<->BSC
> bearer capa='given by MS' speech version='Full Rate given'
> 000000 TRACE 15.01.16 11:37:28.210 CH(1): MNCC_SETUP_IND LCR<->BSC
> calling number=639360100037 imsi=901550000000824 dialing number=12345678
> 000000 DEBUG (in endpoint.cpp/Endpoint() line 48): EPOINT(1): Allocating
> enpoint 1 and connecting it with: ioport
> 000000 DEBUG (in endpoint.cpp/portlist_new() line 150): EPOINT(1)
> allocating port_list, attaching to port 1
> 000000 DEBUG (in appbridge.cpp/EndpointAppBridge() line 31): Bridge
> endpoint created
> 000000 DEBUG (in port.cpp/epointlist_new() line 131): PORT(1) allocating
> epoint_list.
> 000000 TRACE 15.01.16 11:37:28.211 CH(1): MNCC_CALL_PROC_REQ LCR<->BSC
> progress coding=3 location=1 descr=8
> 000000 DEBUG (in port.cpp/new_state() line 283): PORT(gsm-0-in) new state
> PORT_STATE_IDLE --> PORT_STATE_IN_PROCEEDING
> 000000 TRACE 15.01.16 11:37:28.211 CH(1): MNCC_FRAME_RECV LCR<->BSC
> 000000 DEBUG (in gsm_bs.cpp/setup_ind() line 631): Request RTP peer info,
> before forwarding setup
> 000000 DEBUG (in gsm.cpp/rtp_create_ind() line 869): Got RTP peer info
> (7f000001,52103) forwarding setup
> 000000 DEBUG (in message.c/_message_put() line 70): message MESSAGE_SETUP
> written from 140733193388033 to 140733193388033 (memory 6b1a50 at file
> gsm.cpp, line 872)
> 000000 DEBUG (in message.c/message_get() line 115): message MESSAGE_SETUP
> reading from 1 to 140733193388033 (memory 6b1a50)
> 000000 DEBUG (in appbridge.cpp/port_setup() line 94): EPOINT(1) epoint
> received setup from='639360100037' to='12345678'
> 000000 DEBUG (in port.cpp/Port() line 210): new port (2) of type 0x2002,
> name 'sip-0-out' interface 'sip'
> 000000 DEBUG (in sip.cpp/Psip() line 72): Created new Psip(sip-0-out).
> 000000 DEBUG (in endpoint.cpp/portlist_new() line 150): EPOINT(1)
> allocating port_list, attaching to port 2
> 000000 DEBUG (in message.c/_message_put() line 70): message MESSAGE_SETUP
> written from 1 to 2 (memory 6b1a50 at file message.c, line 94)
> 000000 DEBUG (in message.c/_message_put() line 70): message MESSAGE_BRIDGE
> written from 1 to 1 (memory 6b6c00 at file appbridge.cpp, line 222)
> 000000 DEBUG (in message.c/_message_put() line 70): message MESSAGE_BRIDGE
> written from 1 to 2 (memory 6ba6e0 at file appbridge.cpp, line 225)
> 000000 DEBUG (in message.c/message_get() line 115): message MESSAGE_SETUP
> reading from 140733193388033 to 2 (memory 6b1a50)
> 000000 DEBUG (in sip.cpp/message_setup() line 954): Doing Setup (inst
> 0x6acce0)
> 000000 DEBUG (in sip.cpp/message_setup() line 961): RTP info given by
> remote, forward that
> 000000 DEBUG (in sip.cpp/message_setup() line 968): local ip 7f000001 port
> 52103
> 000000 DEBUG (in sip.cpp/message_setup() line 969): remote ip 00000000
> port 0
> nua: nh_create_handle: entering
> 000000 TRACE 15.01.16 11:37:28.816 CH(2): NEW handle handle new=0x6b09c0
> 000000 DEBUG (in sip.cpp/message_setup() line 1038): Using SDP for invite:
> v=0
> o=LCR-Sofia-SIP 0 0 IN IP4 127.0.0.1
> s=SIP Call
> c=IN IP4 127.0.0.1
> t=0 0
> m=audio 52103 RTP/AVP 3
> a=rtpmap:3 GSM/8000
> 000000 TRACE 15.01.16 11:37:28.816 CH(2): INVITE from uri=
> sip:639360100037@127.0.0.1:5062 to uri=sip:12345678@192.168.40.100:5060
> rtp ip=127.0.0.1 port=52103,52104 payload=GSM:3
> nua: nua_invite: entering
> nua(0x6b09c0): sent signal r_invite
> 000000 DEBUG (in port.cpp/new_state() line 283): PORT(sip-0-out) new state
> PORT_STATE_IDLE --> PORT_STATE_OUT_SETUP
> 000000 DEBUG (in sip.cpp/message_setup() line 1069): do proceeding
> 000000 DEBUG (in port.cpp/new_state() line 283): PORT(sip-0-out) new state
> PORT_STATE_OUT_SETUP --> PORT_STATE_OUT_PROCEEDING
> 000000 DEBUG (in message.c/_message_put() line 70): message
> MESSAGE_PROCEEDING written from 2 to 1 (memory 6be1c0 at file sip.cpp, line
> 1072)
> 000000 DEBUG (in port.cpp/epointlist_new() line 131): PORT(2) allocating
> epoint_list.
> 000000 DEBUG (in message.c/message_get() line 115): message MESSAGE_BRIDGE
> reading from 1 to 1 (memory 6b6c00)
> 000000 DEBUG (in port.cpp/message_epoint() line 657): PORT(gsm-0-in)
> bridging to id 1
> nua(0x6b09c0): recv signal r_invite
> 000000 DEBUG (in port.cpp/bridge() line 1305): Port 1 creating not
> existing bridge 1.
> 000000 DEBUG (in message.c/message_get() line 115): message MESSAGE_BRIDGE
> reading from 1 to 2 (memory 6ba6e0)
> 000000 DEBUG (in port.cpp/message_epoint() line 657): PORT(sip-0-out)
> bridging to id 1
> nua: nua_stack_set_params: entering
> 000000 DEBUG (in port.cpp/bridge() line 1290): Port 2 found existing
> bridge 1.
> 000000 DEBUG (in message.c/message_get() line 115): message
> MESSAGE_PROCEEDING reading from 2 to 1 (memory 6be1c0)
> 000000 DEBUG (in appbridge.cpp/port_other() line 259): EPOINT(8) epoint
> received message 7070144 from port
> 000000 DEBUG (in message.c/_message_put() line 70): message
> MESSAGE_PROCEEDING written from 1 to 140733193388033 (memory 6be1c0 at file
> message.c, line 94)
> 000000 DEBUG (in message.c/message_get() line 115): message
> MESSAGE_PROCEEDING reading from 1 to 1 (memory 6be1c0)
> nua(0x6b09c0): adding session usage
> nta_leg_tcreate(0x7ffff0006b00)
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0x7ffff6c52700 (LWP 11520)]
> strlen () at ../sysdeps/x86_64/strlen.S:106
> 106 ../sysdeps/x86_64/strlen.S: No such file or directory.
> (gdb) bt
> #0 strlen () at ../sysdeps/x86_64/strlen.S:106
> #1 0x00007ffff7b70896 in url_xtra (url=url@entry=0x7ffff00075d0) at
> url.c:1048
> #2 0x00007ffff7b2deaf in sip_request_create (home=home@entry=0x7ffff0006fc0,
> method=method@entry=sip_method_invite, name=0x7ffff7b916e2
> <sip_method_name_invite> "INVITE",
> name@entry=0x7ffff7b8ed49 "INVITE", uri=uri@entry=0x7ffff00075d0,
> version=version@entry=0x0) at sip_basic.c:225
> #3 0x00007ffff7ae3512 in nta_msg_request_complete (msg=msg@entry=0x7ffff0006fc0,
> leg=leg@entry=0x7ffff0006b00, method=method@entry=sip_method_invite,
> method_name=method_name@entry=0x7ffff7b8ed49 "INVITE",
> request_uri=0x7ffff00075d0, request_uri@entry=0x0) at nta.c:3890
> #4 0x00007ffff7b07d92 in nua_client_request_sendmsg (cr=cr@entry=0x7ffff0005af0)
> at nua_client.c:803
> #5 0x00007ffff7b08de9 in nua_client_request_try (cr=0x7ffff0005af0) at
> nua_client.c:708
> #6 0x00007ffff7b06b93 in nua_client_init_request0 (cr=0x7ffff0005af0) at
> nua_client.c:605
> #7 nua_client_init_request (cr=0x7ffff0005af0) at nua_client.c:442
> #8 0x00007ffff7b07246 in nua_client_create (nh=nh@entry=0x6b09c0,
> event=event@entry=31, methods=methods@entry=0x7ffff7dc4d20
> <nua_invite_client_methods>, tags=tags@entry=0x6b0eb0)
> at nua_client.c:199
> #9 0x00007ffff7b1cc61 in nua_stack_invite (nua=nua@entry=0x6adc80,
> nh=nh@entry=0x6b09c0, e=e@entry=nua_r_invite, tags=tags@entry=0x6b0eb0)
> at nua_session.c:705
> #10 0x00007ffff7b03eb3 in nua_stack_signal (nua=0x6adc80, msg=<optimized
> out>, ee=0x6b0e88) at nua_stack.c:582
> #11 0x00007ffff7b522b2 in su_base_port_execute_msgs (queue=0x0) at
> su_base_port.c:280
> #12 0x00007ffff7b527bd in su_base_port_run (self=0x7ffff00008c0) at
> su_base_port.c:335
> #13 0x00007ffff7b52f10 in su_pthread_port_clone_main (varg=0x7fffffffe4c0)
> at su_pthread_port.c:324
> #14 0x00007ffff7840182 in start_thread (arg=0x7ffff6c52700) at
> pthread_create.c:312
> #15 0x00007ffff6d4d47d in clone () at
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
>
>
4
4
From: Max <msuraev(a)sysmocom.de>
---
src/bitvec.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/bitvec.c b/src/bitvec.c
index f9341b7..7254674 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -383,14 +383,12 @@ unsigned int bitvec_unpack(struct bitvec *bv, const uint8_t *buffer)
int bitvec_unhex(struct bitvec *bv, const char *src)
{
- unsigned val;
- unsigned write_index = 0;
- unsigned digits = bv->data_len * 2;
- for (unsigned i = 0; i < digits; i++) {
- if (sscanf(src + i, "%1x", &val) < 1) {
+ unsigned val, i, write_index = 0;
+ for (i = 0; i < bv->data_len * 2; i++) {
+ if (sscanf(src + i, "%1x", &val) < 1)
return 1;
- }
- bitvec_write_field(bv, write_index,val, 4);
+
+ bitvec_write_field(bv, write_index, val, 4);
}
return 0;
}
--
2.5.0
2
5
Hey Daniel,
we are working on our separate branches in openbsc: daniel/gprs-iu
and neels/cscn.
Merging them will be nontrivial, at least because I have moved
gprs/sgsn_iu.c to new libiu/iu.c and include/.../iu.h. That's because some
of the stuff there is useful outside of the gprs scope.
Otherwise I've not changed the code much, you have at least a little, so
before we potentially further complicate the changes, we may benefit from
consolidating our branches, sooner rather than later...
Though my cscn code doesn't do anything useful yet, it is in a separate
new subdir, so merging it to master wouldn't break anything. Merging both
our stuffs to master is what I would suggest.
If you merge to master first I volunteer to rebase mine and take on the
hard half of the merge myself. OTOH, if I'm faster ... ;)
(More precisely, I'll bump this in at most two weeks, so plz go for it.)
Opinions/strategies welcome!
~Neels
--
- Neels Hofmeyr <nhofmeyr(a)sysmocom.de> http://www.sysmocom.de/
=======================================================================
* sysmocom - systems for mobile communications GmbH
* Alt-Moabit 93
* 10559 Berlin, Germany
* Sitz / Registered office: Berlin, HRB 134158 B
* Geschäftsführer / Managing Directors: Holger Freyther, Harald Welte
1
0
28 Jan '16
From: Max <msuraev(a)sysmocom.de>
Fix error creeped in while porting code from cpp refs.
Add test case for code in question.
Expand documentatin to clarify function use.
---
src/bitvec.c | 24 +++++++++++++++++++-----
tests/bitvec/bitvec_test.c | 15 +++++++++++++++
tests/bitvec/bitvec_test.ok | 12 ++++++++++++
3 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/src/bitvec.c b/src/bitvec.c
index f9341b7..b88afa6 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -138,6 +138,7 @@ unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n)
* \param[in] bv bit vector on which to operate
* \param[in] bitnr number of bit to be set
* \param[in] bit value to which the bit is to be set
+ * \returns 0 on success, negative value on error
*/
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
enum bit_value bit)
@@ -163,6 +164,7 @@ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
/*! \brief set the next bit inside a bitvec
* \param[in] bv bit vector to be used
* \param[in] bit value of the bit to be set
+ * \returns 0 on success, negative value on error
*/
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
{
@@ -390,11 +392,18 @@ int bitvec_unhex(struct bitvec *bv, const char *src)
if (sscanf(src + i, "%1x", &val) < 1) {
return 1;
}
- bitvec_write_field(bv, write_index,val, 4);
+ bitvec_write_field(bv, write_index, val, 4);
+ write_index += 4;
}
return 0;
}
+/*! \brief read part of the vector
+ * \param[in] bv The boolean vector to work on
+ * \param[in] read_index Where reading supposed to start in the vector
+ * \param[in] len How many bits to read from vector
+ * \returns read bits or negative value on error
+ */
uint64_t bitvec_read_field(struct bitvec *bv, unsigned int read_index, unsigned int len)
{
unsigned int i;
@@ -409,11 +418,16 @@ uint64_t bitvec_read_field(struct bitvec *bv, unsigned int read_index, unsigned
ui |= ((uint64_t)1 << (len - i - 1));
bv->cur_bit++;
}
- read_index += len;
+
return ui;
}
-
+/*! \brief write into the vector
+ * \param[in] bv The boolean vector to work on
+ * \param[in] write_index Where writing supposed to start in the vector
+ * \param[in] len How many bits to write
+ * \returns next write index or negative value on error
+ */
int bitvec_write_field(struct bitvec *bv, unsigned int write_index, uint64_t val, unsigned int len)
{
unsigned int i;
@@ -427,8 +441,8 @@ int bitvec_write_field(struct bitvec *bv, unsigned int write_index, uint64_t val
if (rc)
return rc;
}
- write_index += len;
- return 0;
+
+ return write_index + len;
}
/*! @} */
diff --git a/tests/bitvec/bitvec_test.c b/tests/bitvec/bitvec_test.c
index 624e334..dde8448 100644
--- a/tests/bitvec/bitvec_test.c
+++ b/tests/bitvec/bitvec_test.c
@@ -55,8 +55,23 @@ static void test_byte_ops()
printf("=== end %s ===\n", __func__);
}
+static void test_unhex(char *hex)
+{
+ struct bitvec b;
+ uint8_t d[64] = {0};
+ b.data = d;
+ b.data_len = sizeof(d);
+ b.cur_bit = 0;
+ printf("%d -=>\n", bitvec_unhex(&b, hex));
+ printf("%s\n%s\n", osmo_hexdump_nospc(d, 64), osmo_hexdump_nospc(hex, 23));
+}
+
int main(int argc, char **argv)
{
test_byte_ops();
+ test_unhex("48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b");
+ test_unhex("47240c00400000000000000079eb2ac9402b2b2b2b2b2b");
+ test_unhex("47283c367513ba333004242b2b2b2b2b2b2b2b2b2b2b2b");
+ test_unhex("DEADFACE000000000000000000000000000000BEEFFEED");
return 0;
}
diff --git a/tests/bitvec/bitvec_test.ok b/tests/bitvec/bitvec_test.ok
index 1f329af..17e8fd2 100644
--- a/tests/bitvec/bitvec_test.ok
+++ b/tests/bitvec/bitvec_test.ok
@@ -1,2 +1,14 @@
=== start test_byte_ops ===
=== end test_byte_ops ===
+1 -=>
+48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+1 -=>
+47240c00400000000000000079eb2ac9402b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+47240c00400000000000000079eb2ac9402b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+1 -=>
+47283c367513ba333004242b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+47283c367513ba333004242b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+1 -=>
+deadface000000000000000000000000000000beeffeed0000000000000000000000000000000000000000000000000000000000000000000000000000000000
+deadface000000000000000000000000000000beeffeed0000000000000000000000000000000000000000000000000000000000000000000000000000000000
--
2.5.0
3
2
Hi list,
it's time for a summary of our progress in the 3G realm.
Just this minute, I have posted a blog entry that describes our aim as
well as the current development status in abundant detail. At your
convenience, see for yourself and visit:
https://openbsc.osmocom.org/trac/blog/3G_2016_01
Happy hacking!
~Neels
--
- Neels Hofmeyr <nhofmeyr(a)sysmocom.de> http://www.sysmocom.de/
=======================================================================
* sysmocom - systems for mobile communications GmbH
* Alt-Moabit 93
* 10559 Berlin, Germany
* Sitz / Registered office: Berlin, HRB 134158 B
* Geschäftsführer / Managing Directors: Holger Freyther, Harald Welte
1
0
Hi,
my attention was directed at the gprs_shift_v_fixed() function:
int gprs_shift_v_fixed(uint8_t **data, size_t *data_len,
size_t len, uint8_t **value)
It advances the *data pointer and returns a *value pointer.
So it could technically be consting much more aggressively.
However, the compiler warnings confuse me.
I've created this test code to illustrate; the ints should be treated read-only
by func():
void func(const int **yyy)
{
(*yyy) ++;
}
int main(void)
{
int y[2] = {23, 42}; // mutable "by coincidence"
int *yy = y;
func(&yy);
return *yy; // returns 42
}
The idea is that yy is a pointer to a mutable int. func() expects a const int,
but what harm could be done by passing a mutable-int pointer as an
immutable-int pointer. Apparently this harm:
check.c: In function ‘main’:
check.c:10:14: warning: passing argument 1 of ‘func’ from incompatible pointer type
func(&yy);
^
check.c:1:6: note: expected ‘const int **’ but argument is of type ‘int **’
void func(const int **yyy)
Changing yy to a pointer-to-const-int clears the warning:
const int *yy = y;
func(&yy);
I'm expecting the const to apply to the int pointed at, so I should be able to
modify the pointer while the compiler shouldn't waste a thought at whether the
int pointed at is const or not. func() is stricter, not less strict than y[].
To further illustrate, this would make the pointer address itself immutable,
which is not what I want:
int * const yy = y;
I just want to declare the underlying int data to be unchangeable by func(),
not caring whether the caller passes a const int or a mutable int buffer.
Is the compiler merely nitpicking or am I getting something wrong
fundamentally?
Thanks!
~Neels
--
- Neels Hofmeyr <nhofmeyr(a)sysmocom.de> http://www.sysmocom.de/
=======================================================================
* sysmocom - systems for mobile communications GmbH
* Alt-Moabit 93
* 10559 Berlin, Germany
* Sitz / Registered office: Berlin, HRB 134158 B
* Geschäftsführer / Managing Directors: Holger Freyther, Harald Welte
2
2