#include <osmocom/logging.h>
#include <osmocom/networks.h>
#include <osmocom/l1ctl.h>
+#include <osmocom/vty.h>
+static void start_rr_t_monitor(struct gsm48_rrlayer *rr, int sec, int micro);
+static void stop_rr_t_monitor(struct gsm48_rrlayer *rr);
static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg);
static int gsm48_rr_dl_est(struct osmocom_ms *ms);
return work;
}
+int gsm48_rr_start_monitor(struct osmocom_ms *ms)
+{
+ ms->rrlayer.monitor = 1;
+ memset(&ms->meas, 0, sizeof(&ms->meas));
+ start_rr_t_monitor(&ms->rrlayer, 1, 0);
+
+ return 0;
+}
+
+int gsm48_rr_stop_monitor(struct osmocom_ms *ms)
+{
+ ms->rrlayer.monitor = 0;
+ memset(&ms->meas, 0, sizeof(&ms->meas));
+ stop_rr_t_monitor(&ms->rrlayer);
+
+ return 0;
+}
+
/*
* timers handling
*/
+/* special timer to monitor measurements */
+static void timeout_rr_monitor(void *arg)
+{
+ struct gsm48_rrlayer *rr = arg;
+ struct gsm322_cellsel *cs = &rr->ms->cellsel;
+ struct rx_meas_stat *meas = &rr->ms->meas;
+ struct gsm_settings *set = &rr->ms->settings;
+ int rxlev, berr;
+ uint8_t ch_type, ch_subch, ch_ts;
+ char text[256];
+
+ if (!cs->selected) {
+ sprintf(text, "MON: no cell selected");
+ } else if (!meas->frames) {
+ sprintf(text, "MON: no cell info");
+ } else {
+ rxlev = meas->rxlev / meas->frames;
+ berr = meas->berr / meas->frames;
+ sprintf(text, "MON: arfcn=%d lev=%s ber=%2d LAI=%s %s %04x "
+ "ID=%04x", cs->sel_arfcn, gsm_print_rxlev(rxlev),
+ berr, gsm_print_mcc(cs->sel_mcc),
+ gsm_print_mnc(cs->sel_mnc), cs->sel_lac, cs->sel_id);
+ if (rr->state == GSM48_RR_ST_DEDICATED) {
+ rsl_dec_chan_nr(rr->cd_now.chan_nr, &ch_type,
+ &ch_subch, &ch_ts);
+ sprintf(text + strlen(text), " TA=%d pwr=%d TS=%d",
+ rr->ind_ta - set->alter_delay,
+ (set->alter_tx_power) ? set->alter_tx_power_value
+ : rr->ind_tx_power, ch_ts);
+ if (ch_type == RSL_CHAN_SDCCH8_ACCH
+ || ch_type == RSL_CHAN_SDCCH4_ACCH)
+ sprintf(text + strlen(text), "/%d", ch_subch);
+ }
+ }
+ vty_notify(rr->ms, "%s\n", text);
+
+ memset(meas, 0, sizeof(*meas));
+ start_rr_t_monitor(rr, 1, 0);
+}
+
/* special timer to ensure that UA is sent before disconnecting channel */
static void timeout_rr_t_rel_wait(void *arg)
{
new_rr_state(rr, GSM48_RR_ST_IDLE);
}
+static void start_rr_t_monitor(struct gsm48_rrlayer *rr, int sec, int micro)
+{
+ rr->t_monitor.cb = timeout_rr_monitor;
+ rr->t_monitor.data = rr;
+ bsc_schedule_timer(&rr->t_monitor, sec, micro);
+}
+
static void start_rr_t_rel_wait(struct gsm48_rrlayer *rr, int sec, int micro)
{
LOGP(DRR, LOGL_INFO, "starting T_rel_wait with %d seconds\n", sec);
bsc_schedule_timer(&rr->t3126, sec, micro);
}
+static void stop_rr_t_monitor(struct gsm48_rrlayer *rr)
+{
+ if (bsc_timer_pending(&rr->t_monitor)) {
+ LOGP(DRR, LOGL_INFO, "stopping pending timer T_monitor\n");
+ bsc_del_timer(&rr->t_monitor);
+ }
+}
+
static void stop_rr_t_rel_wait(struct gsm48_rrlayer *rr)
{
if (bsc_timer_pending(&rr->t_rel_wait)) {
/* setting (new) timing advance */
rr->ind_ta = rr->cd_now.ta;
- LOGP(DRR, LOGL_INFO, "setting indicated ta %d (actual ta %d)\n",
+ LOGP(DRR, LOGL_INFO, "setting indicated TA %d (actual TA %d)\n",
rr->ind_ta, rr->ind_ta - set->alter_delay);
l1ctl_tx_ph_param_req(ms, rr->ind_ta - set->alter_delay,
(set->alter_tx_power) ? set->alter_tx_power_value
rr->rr_est_msg = NULL;
}
+ stop_rr_t_monitor(rr);
stop_rr_t_rel_wait(rr);
stop_rr_t3110(rr);
stop_rr_t3122(rr);
struct l1ctl_info_dl *dl, dl_cpy;
struct l1ctl_data_ind *ccch;
struct lapdm_entity *le;
+ struct rx_meas_stat *meas = &ms->meas;
uint8_t chan_type, chan_ts, chan_ss;
uint8_t gsmtap_chan_type;
struct gsm_time tm;
chan_nr2string(dl->chan_nr), tm.t1, tm.t2, tm.t3,
hexdump(ccch->data, sizeof(ccch->data)));
+ meas->frames++;
+ meas->berr += dl->num_biterr;
+ meas->rxlev += dl->rx_level;
+
if (dl->num_biterr) {
+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);
return 0;
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);
printf("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;
printf("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;
printf("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);
return CMD_SUCCESS;
}
+DEFUN(monitor_network, monitor_network_cmd, "monitor network MS_NAME",
+ "Monitor...\nMonitor network information\nName of MS (see \"show ms\")")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ gsm48_rr_start_monitor(ms);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
+ NO_STR "Monitor...\nDeactivate monitor of network information\n"
+ "Name of MS (see \"show ms\")")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ gsm48_rr_stop_monitor(ms);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(insert_test, insert_test_cmd, "insert testcard MS_NAME [mcc] [mnc]",
"Insert ...\nInsert test card\nName of MS (see \"show ms\")\n"
"Mobile Country Code\nMobile Network Code")
install_element_ve(&show_ba_cmd);
install_element_ve(&show_forb_la_cmd);
install_element_ve(&show_forb_plmn_cmd);
+ install_element_ve(&monitor_network_cmd);
+ install_element_ve(&no_monitor_network_cmd);
install_element(ENABLE_NODE, &insert_test_cmd);
install_element(ENABLE_NODE, &remove_sim_cmd);