diff --git a/src/host/layer23/include/osmocom/gsm322.h b/src/host/layer23/include/osmocom/gsm322.h index 9c44e0bb4..d1ab0bec5 100755 --- a/src/host/layer23/include/osmocom/gsm322.h +++ b/src/host/layer23/include/osmocom/gsm322.h @@ -196,4 +196,6 @@ extern const char *plmn_a_state_names[]; extern const char *plmn_m_state_names[]; extern const char *cs_state_names[]; +char *gsm_print_rxlev(uint8_t rxlev); + #endif /* _GSM322_H */ diff --git a/src/host/layer23/include/osmocom/gsm48_rr.h b/src/host/layer23/include/osmocom/gsm48_rr.h index 16ba2fe2d..c268c243c 100644 --- a/src/host/layer23/include/osmocom/gsm48_rr.h +++ b/src/host/layer23/include/osmocom/gsm48_rr.h @@ -152,6 +152,10 @@ struct gsm48_rrlayer { /* BA range */ uint8_t ba_ranges; uint32_t ba_range[16]; + + /* monitor */ + uint8_t monitor; + struct timer_list t_monitor; }; const char *get_rr_name(int value); @@ -168,5 +172,7 @@ int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg); int gsm48_rr_los(struct osmocom_ms *ms); int gsm48_rr_rach_conf(struct osmocom_ms *ms, uint32_t fn); extern const char *gsm48_rr_state_names[]; +int gsm48_rr_start_monitor(struct osmocom_ms *ms); +int gsm48_rr_stop_monitor(struct osmocom_ms *ms); #endif /* _GSM48_RR_H */ diff --git a/src/host/layer23/include/osmocom/osmocom_data.h b/src/host/layer23/include/osmocom/osmocom_data.h index 1be19a3cf..6fdeef787 100644 --- a/src/host/layer23/include/osmocom/osmocom_data.h +++ b/src/host/layer23/include/osmocom/osmocom_data.h @@ -24,6 +24,13 @@ struct osmol2_entity { osmol2_cb_t msg_handler; }; +/* RX measurement statistics */ +struct rx_meas_stat { + uint32_t frames; + uint32_t berr; + uint32_t rxlev; +}; + /* One Mobilestation for osmocom */ struct osmocom_ms { struct llist_head entity; @@ -39,6 +46,8 @@ struct osmocom_ms { struct osmol2_entity l2_entity; + struct rx_meas_stat meas; + struct gsm48_rrlayer rrlayer; struct gsm322_plmn plmn; struct gsm322_cellsel cellsel; diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c index 04e06e5f3..68dcd5688 100644 --- a/src/host/layer23/src/gsm322.c +++ b/src/host/layer23/src/gsm322.c @@ -219,7 +219,7 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg) * support */ -static char *gsm_print_rxlev(uint8_t rxlev) +char *gsm_print_rxlev(uint8_t rxlev) { static char string[5]; if (rxlev == 0) diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c index cbcb9afac..2aaa02704 100644 --- a/src/host/layer23/src/gsm48_rr.c +++ b/src/host/layer23/src/gsm48_rr.c @@ -59,7 +59,10 @@ #include #include #include +#include +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); @@ -388,10 +391,68 @@ int gsm48_rsl_dequeue(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) { @@ -453,6 +514,13 @@ static void timeout_rr_t3126(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); @@ -485,6 +553,14 @@ static void start_rr_t3126(struct gsm48_rrlayer *rr, int sec, int micro) 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)) { @@ -3073,7 +3149,7 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms) /* 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 @@ -4156,6 +4232,7 @@ int gsm48_rr_exit(struct osmocom_ms *ms) rr->rr_est_msg = NULL; } + stop_rr_t_monitor(rr); stop_rr_t_rel_wait(rr); stop_rr_t3110(rr); stop_rr_t3122(rr); diff --git a/src/host/layer23/src/l1ctl.c b/src/host/layer23/src/l1ctl.c index 5bb375c6c..9d5919810 100644 --- a/src/host/layer23/src/l1ctl.c +++ b/src/host/layer23/src/l1ctl.c @@ -154,6 +154,7 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) 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; @@ -175,7 +176,12 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) 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; @@ -280,6 +286,8 @@ 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); @@ -371,6 +379,8 @@ int tx_ph_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn, 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; @@ -398,6 +408,8 @@ int tx_ph_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn, 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; @@ -426,6 +438,8 @@ int tx_ph_dm_rel_req(struct osmocom_ms *ms) 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); diff --git a/src/host/layer23/src/vty_interface.c b/src/host/layer23/src/vty_interface.c index 0df2bb27c..192b864e2 100644 --- a/src/host/layer23/src/vty_interface.c +++ b/src/host/layer23/src/vty_interface.c @@ -308,6 +308,35 @@ DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME", 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") @@ -1015,6 +1044,8 @@ int ms_vty_init(void) 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);