summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src
diff options
context:
space:
mode:
authorAndreas.Eversberg <jolly@eversberg.eu>2010-10-12 08:26:48 +0000
committerAndreas.Eversberg <jolly@eversberg.eu>2010-10-12 08:26:48 +0000
commit6d4915b91b13fa879e0dd75d2c275e82b5a5634c (patch)
treee385c97e0fecc0591ec6d7f17bf3925ec2fae258 /src/host/layer23/src
parent86f4d80b7ffab98efeb8fb28b393d743de897806 (diff)
[layer23] Implementation of signal loss criteria as defined in TS 05.08
There are two criterions for lossing a signal, idle mode and dedicated mode. A counter counts down when a frame is dropped, and counts up when a valid frame is received on certain channel. The loss criterion is reached, if the counter reaches 0. The values added to / removed from the counter and the limits depend on the process.
Diffstat (limited to 'src/host/layer23/src')
-rw-r--r--src/host/layer23/src/common/l1ctl.c54
-rw-r--r--src/host/layer23/src/mobile/gsm322.c36
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c43
-rw-r--r--src/host/layer23/src/mobile/settings.c1
-rw-r--r--src/host/layer23/src/mobile/support.c1
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c16
6 files changed, 100 insertions, 51 deletions
diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c
index be84bf95..0b25008e 100644
--- a/src/host/layer23/src/common/l1ctl.c
+++ b/src/host/layer23/src/common/l1ctl.c
@@ -160,7 +160,51 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
meas->berr += dl->num_biterr;
meas->rxlev += dl->rx_level;
- if (dl->num_biterr) {
+ /* counting loss criteria */
+ if (!(dl->link_id & 0x40)) {
+ switch (chan_type) {
+ case RSL_CHAN_PCH_AGCH:
+ if (!meas->ds_fail)
+ break;
+ if (dl->fire_crc >= 2)
+ meas->dsc -= 4;
+ else
+ meas->dsc += 1;
+ if (meas->dsc > meas->ds_fail)
+ meas->dsc = meas->ds_fail;
+ if (meas->dsc < meas->ds_fail)
+ printf("LOSS counter for CCCH %d\n", meas->dsc);
+ if (meas->dsc > 0)
+ break;
+ meas->ds_fail = 0;
+ dispatch_signal(SS_L1CTL, S_L1CTL_LOSS_IND, ms);
+ break;
+ }
+ } else {
+ switch (chan_type) {
+ case RSL_CHAN_Bm_ACCHs:
+ case RSL_CHAN_Lm_ACCHs:
+ case RSL_CHAN_SDCCH4_ACCH:
+ case RSL_CHAN_SDCCH8_ACCH:
+ if (!meas->rl_fail)
+ break;
+ if (dl->fire_crc >= 2)
+ meas->s -= 1;
+ else
+ meas->s += 2;
+ if (meas->s > meas->rl_fail)
+ meas->s = meas->rl_fail;
+ if (meas->s < meas->rl_fail)
+ printf("LOSS counter for ACCH %d\n", meas->s);
+ if (meas->s > 0)
+ break;
+ meas->rl_fail = 0;
+ dispatch_signal(SS_L1CTL, S_L1CTL_LOSS_IND, ms);
+ break;
+ }
+ }
+
+ if (dl->fire_crc >= 2) {
printf("Dropping frame with %u bit errors\n", dl->num_biterr);
LOGP(DL1C, LOGL_NOTICE, "Dropping frame with %u bit errors\n",
dl->num_biterr);
@@ -266,8 +310,6 @@ int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
if (!msg)
return -1;
- memset(&ms->meas, 0, sizeof(ms->meas));
-
req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req));
req->band_arfcn = htons(osmo_make_band_arfcn(ms, arfcn));
req->timeout = htons(timeout);
@@ -399,8 +441,6 @@ int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Est Req (arfcn=%u, "
"chan_nr=0x%02x)\n", band_arfcn, chan_nr);
- memset(&ms->meas, 0, sizeof(ms->meas));
-
ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
ul->chan_nr = chan_nr;
ul->link_id = 0;
@@ -430,8 +470,6 @@ int l1ctl_tx_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Est Req (maio=%u, hsn=%u, "
"chan_nr=0x%02x)\n", maio, hsn, chan_nr);
- memset(&ms->meas, 0, sizeof(ms->meas));
-
ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
ul->chan_nr = chan_nr;
ul->link_id = 0;
@@ -522,8 +560,6 @@ int l1ctl_tx_dm_rel_req(struct osmocom_ms *ms)
LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Rel Req\n");
- memset(&ms->meas, 0, sizeof(ms->meas));
-
ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
return osmo_send_l1(ms, msg);
diff --git a/src/host/layer23/src/mobile/gsm322.c b/src/host/layer23/src/mobile/gsm322.c
index 92287275..807c6624 100644
--- a/src/host/layer23/src/mobile/gsm322.c
+++ b/src/host/layer23/src/mobile/gsm322.c
@@ -236,6 +236,7 @@ static int gsm322_sync_to_cell(struct gsm322_cellsel *cs)
{
struct osmocom_ms *ms = cs->ms;
struct gsm48_sysinfo *s = cs->si;
+ struct rx_meas_stat *meas = &ms->meas;
cs->ccch_state = GSM322_CCCH_ST_INIT;
if (s && s->si3) {
@@ -257,6 +258,8 @@ static int gsm322_sync_to_cell(struct gsm322_cellsel *cs)
cs->ccch_mode = CCCH_MODE_NONE;
}
+ meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
+
l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
return l1ctl_tx_fbsb_req(ms, cs->arfcn,
L1CTL_FBSB_F_FB01SB, 100, 0,
@@ -443,30 +446,6 @@ void start_cs_timer(struct gsm322_cellsel *cs, int sec, int micro)
bsc_schedule_timer(&cs->timer, sec, micro);
}
-/* start loss timer */
-void start_loss_timer(struct gsm322_cellsel *cs, int sec, int micro)
-{
- /* update timer */
- cs->timer.cb = gsm322_cs_loss;
- cs->timer.data = cs;
- if (bsc_timer_pending(&cs->timer)) {
- struct timeval current_time;
- unsigned long long currentTime;
-
- gettimeofday(&current_time, NULL);
- currentTime = current_time.tv_sec * 1000000LL
- + current_time.tv_usec;
- currentTime += sec * 1000000LL + micro;
- cs->timer.timeout.tv_sec = currentTime / 1000000LL;
- cs->timer.timeout.tv_usec = currentTime % 1000000LL;
-
- return;
- }
-
- LOGP(DCS, LOGL_DEBUG, "Starting loss CS timer with %d seconds.\n", sec);
- bsc_schedule_timer(&cs->timer, sec, micro);
-}
-
/* stop cell selection timer */
static void stop_cs_timer(struct gsm322_cellsel *cs)
{
@@ -2465,6 +2444,10 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
|| cs->state == GSM322_HPLMN_SEARCH)
start_cs_timer(cs, ms->support.scan_to, 0);
// TODO: timer depends on BCCH config
+
+ /* set downlink signalling failure criterion */
+ ms->meas.ds_fail = ms->meas.dsc = ms->settings.dsc_max;
+ LOGP(DRR, LOGL_INFO, "using DSC of %d\n", ms->meas.dsc);
}
break;
case S_L1CTL_FBSB_ERR:
@@ -2488,6 +2471,11 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
else
gsm322_cs_timeout(cs);
break;
+ case S_L1CTL_LOSS_IND:
+ ms = signal_data;
+ cs = &ms->cellsel;
+ gsm322_cs_loss(cs);
+ break;
case S_L1CTL_RESET:
ms = signal_data;
if (ms->mmlayer.power_off_idle) {
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c
index 53cb3b34..86630c3c 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -413,6 +413,7 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
/* release dedicated mode, if any */
l1ctl_tx_dm_rel_req(rr->ms);
+ rr->ms->meas.rl_fail = 0;
rr->dm_est = 0;
l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_FULL);
/* free establish message, if any */
@@ -644,7 +645,7 @@ static void timeout_rr_meas(void *arg)
if (rr->dm_est)
gsm48_rr_tx_meas_rep(rr->ms);
- memset(meas, 0, sizeof(*meas));
+ meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
start_rr_t_meas(rr, 1, 0);
}
@@ -2266,6 +2267,7 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
/* NOTE: pseudo length is not in this structure, so we skip */
struct gsm48_system_information_type_6 *si = msgb_l3(msg) + 1;
struct gsm48_sysinfo *s = ms->cellsel.si;
+ struct rx_meas_stat *meas = &ms->meas;
int payload_len = msgb_l3len(msg) - sizeof(*si) - 1;
if (!s) {
@@ -2303,6 +2305,8 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
"lac 0x%04x SACCH-timeout %d)\n", gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc), s->lac, s->sacch_radio_link_timeout);
+ meas->rl_fail = meas->s = s->sacch_radio_link_timeout;
+ LOGP(DRR, LOGL_INFO, "using (new) SACCH timeout %d\n", meas->rl_fail);
s->si6 = 1;
return gsm48_new_sysinfo(ms, si->system_information);
@@ -3148,6 +3152,7 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
struct gsm48_sysinfo *s = ms->cellsel.si;
struct rx_meas_stat *meas = &ms->meas;
uint8_t ch_type, ch_subch, ch_ts;
+ uint8_t timeout = 64;
/* setting (new) timing advance */
LOGP(DRR, LOGL_INFO, "setting indicated TA %d (actual TA %d)\n",
@@ -3155,13 +3160,29 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
l1ctl_tx_param_req(ms, cd->ind_ta - set->alter_delay,
(set->alter_tx_power) ? set->alter_tx_power_value
: cd->ind_tx_power);
+
+ /* reset measurement and link timeout */
+ meas->ds_fail = 0;
+ if (s) {
+ if (s->sacch_radio_link_timeout) {
+ timeout = s->sacch_radio_link_timeout;
+ LOGP(DRR, LOGL_INFO, "using last SACCH timeout %d\n",
+ timeout);
+ } else if (s->bcch_radio_link_timeout) {
+ timeout = s->bcch_radio_link_timeout;
+ LOGP(DRR, LOGL_INFO, "using last BCCH timeout %d\n",
+ timeout);
+ }
+ }
+ meas->rl_fail = meas->s = timeout;
+
/* setting initial (invalid) measurement report, resetting SI5* */
if (s) {
memset(s->si5_msg, 0, sizeof(s->si5_msg));
memset(s->si5b_msg, 0, sizeof(s->si5b_msg));
memset(s->si5t_msg, 0, sizeof(s->si5t_msg));
- memset(meas, 0, sizeof(*meas));
}
+ meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
rr->meas.nc_num = 0;
stop_rr_t_meas(rr);
start_rr_t_meas(rr, 1, 0);
@@ -4533,6 +4554,7 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "suspension coplete, leaving dedicated "
"mode\n");
l1ctl_tx_dm_rel_req(ms);
+ ms->meas.rl_fail = 0;
rr->dm_est = 0;
l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
@@ -4891,7 +4913,6 @@ static int gsm48_rr_rx_acch(struct osmocom_ms *ms, struct msgb *msg)
/* unit data from layer 2 to RR layer */
static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
- struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct tlv_parsed tv;
@@ -4911,21 +4932,6 @@ static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
&& cs->ccch_state != GSM322_CCCH_ST_DATA)
return -EINVAL;
- /* when camping, start/reset loss timer */
- if (cs->state == GSM322_C3_CAMPED_NORMALLY
- || cs->state == GSM322_C7_CAMPED_ANY_CELL) {
- struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
-#ifdef TODO
- set radio link timeout on layer 1
- it is the number of subsequent BCCH blocks. (about 1/4 seconds)
-#else
- /* use maximu loss timer, if to value is not available yet */
- start_loss_timer(cs, ((rr->state == GSM48_RR_ST_DEDICATED)
- ? ((s->sacch_radio_link_timeout) ? : 64)
- : s->bcch_radio_link_timeout) / 4, 0);
-#endif
- }
-
/* temporary moved here until confirm is fixed */
if (cs->ccch_state != GSM322_CCCH_ST_DATA) {
LOGP(DCS, LOGL_INFO, "Channel provides data.\n");
@@ -5062,6 +5068,7 @@ static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
/* deactivate channel */
l1ctl_tx_dm_rel_req(ms);
+ ms->meas.rl_fail = 0;
rr->dm_est = 0;
l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
diff --git a/src/host/layer23/src/mobile/settings.c b/src/host/layer23/src/mobile/settings.c
index cbef280b..37e0dd84 100644
--- a/src/host/layer23/src/mobile/settings.c
+++ b/src/host/layer23/src/mobile/settings.c
@@ -63,6 +63,7 @@ int gsm_settings_init(struct osmocom_ms *ms)
set->half_v3 = sup->half_v3;
set->ch_cap = sup->ch_cap;
set->min_rxlev_db = sup->min_rxlev_db;
+ set->dsc_max = sup->dsc_max;
if (sup->half_v1 || sup->half_v3)
set->half = 1;
diff --git a/src/host/layer23/src/mobile/support.c b/src/host/layer23/src/mobile/support.c
index beadc783..34952dc2 100644
--- a/src/host/layer23/src/mobile/support.c
+++ b/src/host/layer23/src/mobile/support.c
@@ -101,6 +101,7 @@ void gsm_support_init(struct osmocom_ms *ms)
sup->min_rxlev_db = -100; // TODO
sup->sync_to = 6; /* how long to wait sync (0.9 s) */
sup->scan_to = 4; /* how long to wait for all sysinfos (>=4 s) */
+ sup->dsc_max = 90; /* the specs defines 90 */
/* codec */
sup->full_v1 = 1;
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index af994b42..e3d34fe0 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -916,6 +916,7 @@ static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
SUP_WRITE(half_v1, "half-speech-v1");
SUP_WRITE(half_v3, "half-speech-v3");
vty_out(vty, " min-rxlev %d%s", set->min_rxlev_db, VTY_NEWLINE);
+ vty_out(vty, " dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
vty_out(vty, " exit%s", VTY_NEWLINE);
vty_out(vty, " test-sim%s", VTY_NEWLINE);
vty_out(vty, " imsi %s%s", set->test_imsi, VTY_NEWLINE);
@@ -1528,6 +1529,20 @@ DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
return CMD_SUCCESS;
}
+DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
+ "Set the maximum DSC value. Standard is 90. Increase to make mobile "
+ "more reliable against bad RX signal. This increase the propability "
+ "of missing a paging requests\n"
+ "DSC initial and maximum value (standard is 90)")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ set->dsc_max = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
/* per testsim config */
DEFUN(cfg_ms_testsim, cfg_ms_testsim_cmd, "test-sim",
"Configure test SIM emulation")
@@ -1867,6 +1882,7 @@ int ms_vty_init(void)
install_element(SUPPORT_NODE, &cfg_ms_sup_half_v3_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v3_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
install_node(&testsim_node, config_write_dummy);
install_default(TESTSIM_NODE);
install_element(TESTSIM_NODE, &ournode_exit_cmd);