[layer23] Implementation of signal loss criteria as defined in TS 05.08
authorAndreas.Eversberg <jolly@eversberg.eu>
Tue, 12 Oct 2010 08:26:48 +0000 (08:26 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Tue, 12 Oct 2010 08:26:48 +0000 (08:26 +0000)
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.

src/host/layer23/include/osmocom/bb/common/osmocom_data.h
src/host/layer23/include/osmocom/bb/mobile/settings.h
src/host/layer23/include/osmocom/bb/mobile/support.h
src/host/layer23/src/common/l1ctl.c
src/host/layer23/src/mobile/gsm322.c
src/host/layer23/src/mobile/gsm48_rr.c
src/host/layer23/src/mobile/settings.c
src/host/layer23/src/mobile/support.c
src/host/layer23/src/mobile/vty_interface.c

index a20b177..bc0c7d8 100644 (file)
@@ -40,6 +40,10 @@ struct rx_meas_stat {
        uint32_t snr;
        uint32_t berr;
        uint32_t rxlev;
+
+       /* counters loss criterion */
+       int16_t dsc, ds_fail;
+       int16_t s, rl_fail;
 };
 
 /* One Mobilestation for osmocom */
@@ -76,6 +80,7 @@ enum osmobb_meas_sig {
        S_L1CTL_PM_DONE,
        S_L1CTL_CCCH_MODE_CONF,
        S_L1CTL_TCH_MODE_CONF,
+       S_L1CTL_LOSS_IND,
 };
 
 struct osmobb_fbsb_res {
index 4c66f34..2437951 100644 (file)
@@ -64,6 +64,9 @@ struct gsm_settings {
        uint8_t                 half_v3;
        uint8_t                 ch_cap; /* channel capability */
        int8_t                  min_rxlev_db; /* min DB to access */
+
+       /* radio */
+       uint16_t                dsc_max;
 };
 
 int gsm_settings_init(struct osmocom_ms *ms);
index b609b7d..cbe6e19 100644 (file)
@@ -76,6 +76,7 @@ struct gsm_support {
        int8_t min_rxlev_db;
        uint8_t scan_to;
        uint8_t sync_to;
+       uint16_t dsc_max; /* maximum dl signal failure counter */
 
        /* codecs */
        uint8_t full_v1;
index be84bf9..0b25008 100644 (file)
@@ -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);
index 9228727..807c662 100644 (file)
@@ -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) {
index 53cb3b3..86630c3 100644 (file)
@@ -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);
 
index cbef280..37e0dd8 100644 (file)
@@ -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;
index beadc78..34952dc 100644 (file)
@@ -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;
index af994b4..e3d34fe 100644 (file)
@@ -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);