[layer23] Correctly report to restart mobile instance after band change
[osmocom-bb.git] / src / host / layer23 / src / mobile / vty_interface.c
index 0614c6f..f5ccac3 100644 (file)
@@ -115,6 +115,7 @@ int vty_check_number(struct vty *vty, const char *number)
 }
 
 int vty_reading = 0;
+static int hide_default = 0;
 
 static void vty_restart(struct vty *vty, struct osmocom_ms *ms)
 {
@@ -126,6 +127,13 @@ static void vty_restart(struct vty *vty, struct osmocom_ms *ms)
                "change to take effect!%s", ms->name, VTY_NEWLINE);
 }
 
+static void vty_restart_if_started(struct vty *vty, struct osmocom_ms *ms)
+{
+       if (!ms->started)
+               return;
+       vty_restart(vty, ms);
+}
+
 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
 {
        struct osmocom_ms *ms;
@@ -195,27 +203,40 @@ static void gsm_ms_dump(struct osmocom_ms *ms, struct vty *vty)
                return;
 
        if (set->plmn_mode == PLMN_MODE_AUTO)
-               vty_out(vty, "  automatic network selection state: %s%s", 
-                       plmn_a_state_names[ms->plmn.state], VTY_NEWLINE);
+               vty_out(vty, "  automatic network selection state: %s%s",
+                       get_a_state_name(ms->plmn.state), VTY_NEWLINE);
        else
-               vty_out(vty, "  manual network selection state: %s%s", 
-                       plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
-       vty_out(vty, "  cell selection state: %s",
-               cs_state_names[ms->cellsel.state]);
-       if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
-               vty_out(vty, " (ARFCN %s)",
-                       gsm_print_arfcn(ms->cellsel.sel_arfcn));
-       vty_out(vty, "%s", VTY_NEWLINE);
-       vty_out(vty, "  radio ressource layer state: %s%s", 
+               vty_out(vty, "  manual network selection state   : %s%s",
+                       get_m_state_name(ms->plmn.state), VTY_NEWLINE);
+       if (ms->plmn.mcc)
+               vty_out(vty, "                                     MCC=%s "
+                       "MNC=%s (%s, %s)%s", gsm_print_mcc(ms->plmn.mcc),
+                       gsm_print_mnc(ms->plmn.mnc), gsm_get_mcc(ms->plmn.mcc),
+                       gsm_get_mnc(ms->plmn.mcc, ms->plmn.mnc), VTY_NEWLINE);
+       vty_out(vty, "  cell selection state: %s%s",
+               get_cs_state_name(ms->cellsel.state), VTY_NEWLINE);
+       if (ms->cellsel.sel_mcc) {
+               vty_out(vty, "                        ARFCN=%s MCC=%s MNC=%s "
+                       "LAC=0x%04x CELLID=0x%04x%s",
+                       gsm_print_arfcn(ms->cellsel.sel_arfcn),
+                       gsm_print_mcc(ms->cellsel.sel_mcc),
+                       gsm_print_mnc(ms->cellsel.sel_mnc),
+                       ms->cellsel.sel_lac, ms->cellsel.sel_id, VTY_NEWLINE);
+               vty_out(vty, "                        (%s, %s)%s",
+                       gsm_get_mcc(ms->cellsel.sel_mcc),
+                       gsm_get_mnc(ms->cellsel.sel_mcc, ms->cellsel.sel_mnc),
+                       VTY_NEWLINE);
+       }
+       vty_out(vty, "  radio ressource layer state: %s%s",
                gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
-       vty_out(vty, "  mobility management layer state: %s", 
+       vty_out(vty, "  mobility management layer state: %s",
                gsm48_mm_state_names[ms->mmlayer.state]);
        if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE)
-               vty_out(vty, ", %s", 
+               vty_out(vty, ", %s",
                        gsm48_mm_substate_names[ms->mmlayer.substate]);
        vty_out(vty, "%s", VTY_NEWLINE);
        llist_for_each_entry(trans, &ms->trans_list, entry) {
-               vty_out(vty, "  call control state: %s%s", 
+               vty_out(vty, "  call control state: %s%s",
                        gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE);
        }
 }
@@ -300,7 +321,7 @@ DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
        if (!ms)
                return CMD_WARNING;
 
-       gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
+       gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SUPPORT, print_vty,
                vty);
 
        return CMD_SUCCESS;
@@ -340,6 +361,21 @@ DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023> [pcs]",
        return CMD_SUCCESS;
 }
 
+DEFUN(show_nbcells, show_nbcells_cmd, "show neighbour-cells MS_NAME",
+       SHOW_STR "Display information about current neighbour cells\n"
+       "Name of MS (see \"show ms\")")
+{
+       struct osmocom_ms *ms;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       gsm322_dump_nb_list(&ms->cellsel, print_vty, vty);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [MCC] [MNC]",
        SHOW_STR "Display information about band allocations\n"
        "Name of MS (see \"show ms\")\nMobile Country Code\n"
@@ -430,9 +466,9 @@ DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
 }
 
 DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [MCC] [MNC] [LAC] [TMSI]",
-       "SIM actions\nInsert test card\nName of MS (see \"show ms\")\n"
+       "SIM actions\nAttach bulit in test SIM\nName of MS (see \"show ms\")\n"
        "Mobile Country Code of RPLMN\nMobile Network Code of RPLMN\n"
-       "Optionally locatio area code\nOptionally current assigned TMSI")
+       "Optionally location area code\nOptionally current assigned TMSI")
 {
        struct osmocom_ms *ms;
        uint16_t mcc = 0x001, mnc = 0x01f, lac = 0x0000;
@@ -443,7 +479,7 @@ DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [MCC] [MNC] [LAC] [TMSI]",
                return CMD_WARNING;
 
        if (ms->subscr.sim_valid) {
-               vty_out(vty, "SIM already presend, remove first!%s",
+               vty_out(vty, "SIM already attached, remove first!%s",
                        VTY_NEWLINE);
                return CMD_WARNING;
        }
@@ -473,7 +509,7 @@ DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [MCC] [MNC] [LAC] [TMSI]",
 }
 
 DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
-       "SIM actions\nSelect SIM from reader\nName of MS (see \"show ms\")")
+       "SIM actions\nAttach SIM from reader\nName of MS (see \"show ms\")")
 {
        struct osmocom_ms *ms;
 
@@ -482,7 +518,7 @@ DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
                return CMD_WARNING;
 
        if (ms->subscr.sim_valid) {
-               vty_out(vty, "SIM already presend, remove first!%s",
+               vty_out(vty, "SIM already attached, remove first!%s",
                        VTY_NEWLINE);
                return CMD_WARNING;
        }
@@ -493,7 +529,7 @@ DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
 }
 
 DEFUN(sim_remove, sim_remove_cmd, "sim remove MS_NAME",
-       "SIM actions\nRemove SIM card\nName of MS (see \"show ms\")")
+       "SIM actions\nDetach SIM card\nName of MS (see \"show ms\")")
 {
        struct osmocom_ms *ms;
 
@@ -502,7 +538,7 @@ DEFUN(sim_remove, sim_remove_cmd, "sim remove MS_NAME",
                return CMD_WARNING;
 
        if (!ms->subscr.sim_valid) {
-               vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
+               vty_out(vty, "No SIM attached!%s", VTY_NEWLINE);
                return CMD_WARNING;
        }
 
@@ -657,9 +693,11 @@ DEFUN(sim_lai, sim_lai_cmd, "sim lai MS_NAME MCC MNC LAC",
        return CMD_SUCCESS;
 }
 
-DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
+DEFUN(network_select, network_select_cmd,
+       "network select MS_NAME MCC MNC [force]",
        "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
-       "Mobile Country Code\nMobile Network Code")
+       "Mobile Country Code\nMobile Network Code\n"
+       "Force selecting a network that is not in the list")
 {
        struct osmocom_ms *ms;
        struct gsm322_plmn *plmn;
@@ -675,6 +713,12 @@ DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
                return CMD_WARNING;
        plmn = &ms->plmn;
 
+       if (ms->settings.plmn_mode != PLMN_MODE_MANUAL) {
+               vty_out(vty, "Not in manual network selection mode%s",
+                       VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
        if (!mcc) {
                vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
                return CMD_WARNING;
@@ -684,12 +728,16 @@ DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
                return CMD_WARNING;
        }
 
-       llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
-               if (temp->mcc == mcc &&  temp->mnc == mnc)
-                       found = 1;
-       if (!found) {
-               vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
-               return CMD_WARNING;
+       if (argc < 4) {
+               llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
+                       if (temp->mcc == mcc &&  temp->mnc == mnc)
+                               found = 1;
+               if (!found) {
+                       vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
+                       vty_out(vty, "To force selecting this network, use "
+                               "'force' keyword%s", VTY_NEWLINE);
+                       return CMD_WARNING;
+               }
        }
 
        nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOOSE_PLMN);
@@ -789,6 +837,60 @@ DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
        return CMD_SUCCESS;
 }
 
+DEFUN(test_reselection, test_reselection_cmd, "test re-selection NAME",
+       "Manually trigger cell re-selection\nName of MS (see \"show ms\")")
+{
+       struct osmocom_ms *ms;
+       struct gsm_settings *set;
+       struct msgb *nmsg;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+       set = &ms->settings;
+
+       if (set->stick) {
+               vty_out(vty, "Cannot trigger cell re-selection, because we "
+                       "stick to a cell!%s", VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_RESEL);
+       if (!nmsg)
+               return CMD_WARNING;
+       gsm322_c_event(ms, nmsg);
+
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(delete_forbidden_plmn, delete_forbidden_plmn_cmd,
+       "delete forbidden plmn NAME MCC MNC",
+       "Delete\nForbidden\nplmn\nName of MS (see \"show ms\")\n"
+       "Mobile Country Code\nMobile Network Code")
+{
+       struct osmocom_ms *ms;
+       uint16_t mcc = gsm_input_mcc((char *)argv[1]),
+                mnc = gsm_input_mnc((char *)argv[2]);
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       if (!mcc) {
+               vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+       if (!mnc) {
+               vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       gsm_subscr_del_forbidden_plmn(&ms->subscr, mcc, mnc);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
        "Network ...\nShow results of network search (again)\n"
        "Name of MS (see \"show ms\")")
@@ -931,6 +1033,22 @@ DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate "
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_hide_default, cfg_hide_default_cmd, "hide-default",
+       "Hide most default values in config to make it more compact")
+{
+       hide_default = 1;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_hide_default, cfg_no_hide_default_cmd, "no hide-default",
+       NO_STR "Show default values in config")
+{
+       hide_default = 0;
+
+       return CMD_SUCCESS;
+}
+
 /* per MS config */
 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
        "Select a mobile station to configure\nName of MS (see \"show ms\")")
@@ -1049,8 +1167,9 @@ DEFUN(cfg_no_ms, cfg_no_ms_cmd, "no ms MS_NAME",
 
 #define SUP_WRITE(item, cmd) \
        if (sup->item) \
-               vty_out(vty, "  %s%s%s", (set->item) ? "" : "no ", cmd, \
-                       VTY_NEWLINE);
+               if (!hide_default || !set->item) \
+                       vty_out(vty, "  %s%s%s", (set->item) ? "" : "no ", \
+                       cmd, VTY_NEWLINE);
 
 static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
 {
@@ -1081,17 +1200,26 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
                vty_out(vty, " imei-random %d%s", set->imei_random,
                        VTY_NEWLINE);
        else
-               vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
        if (set->emergency_imsi[0])
                vty_out(vty, " emergency-imsi %s%s", set->emergency_imsi,
                        VTY_NEWLINE);
        else
-               vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
-       vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ", VTY_NEWLINE);
-       vty_out(vty, " %sauto-answer%s", (set->auto_answer) ? "" : "no ",
-               VTY_NEWLINE);
-       vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ", VTY_NEWLINE);
-       vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
+       if (!hide_default || set->cw)
+               vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ",
+                       VTY_NEWLINE);
+       if (!hide_default || set->auto_answer)
+               vty_out(vty, " %sauto-answer%s",
+                       (set->auto_answer) ? "" : "no ", VTY_NEWLINE);
+       if (!hide_default || set->clip)
+               vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ",
+                       VTY_NEWLINE);
+       if (!hide_default || set->clir)
+               vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ",
+                       VTY_NEWLINE);
        if (set->alter_tx_power)
                if (set->alter_tx_power_value)
                        vty_out(vty, " tx-power %d%s",
@@ -1099,22 +1227,27 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
                else
                        vty_out(vty, " tx-power full%s", VTY_NEWLINE);
        else
-               vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
        if (set->alter_delay)
                vty_out(vty, " simulated-delay %d%s", set->alter_delay,
                        VTY_NEWLINE);
        else
-               vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
        if (set->stick)
                vty_out(vty, " stick %d%s%s", set->stick_arfcn & 1023,
                        (set->stick_arfcn & ARFCN_PCS) ? " pcs" : "",
                        VTY_NEWLINE);
        else
-               vty_out(vty, " no stick%s", VTY_NEWLINE);
-       if (set->no_lupd)
-               vty_out(vty, " no location-updating%s", VTY_NEWLINE);
-       else
-               vty_out(vty, " location-updating%s", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, " no stick%s", VTY_NEWLINE);
+       if (!hide_default || set->no_lupd)
+               vty_out(vty, " %slocation-updating%s",
+                       (set->no_lupd) ? "no " : "", VTY_NEWLINE);
+       if (!hide_default || set->no_neighbour)
+               vty_out(vty, " %sneighbour-measurement%s",
+                       (set->no_neighbour) ? "no " : "", VTY_NEWLINE);
        if (set->full_v1 || set->full_v2 || set->full_v3) {
                /* mandatory anyway */
                vty_out(vty, " codec full-speed%s%s",
@@ -1129,9 +1262,10 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
                else
                        vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
        }
-       if (llist_empty(&set->abbrev))
-               vty_out(vty, " no abbrev%s", VTY_NEWLINE);
-       else {
+       if (llist_empty(&set->abbrev)) {
+               if (!hide_default)
+                       vty_out(vty, " no abbrev%s", VTY_NEWLINE);
+       } else {
                llist_for_each_entry(abbrev, &set->abbrev, list)
                        vty_out(vty, " abbrev %s %s%s%s%s", abbrev->abbrev,
                                abbrev->number, (abbrev->name[0]) ? " " : "",
@@ -1155,49 +1289,70 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
        SUP_WRITE(dcs, "dcs");
        SUP_WRITE(pcs, "pcs");
        if (sup->r_gsm || sup->e_gsm || sup->p_gsm)
-               vty_out(vty, "  class-900 %d%s", set->class_900, VTY_NEWLINE);
+               if (!hide_default || sup->class_900 != set->class_900)
+                       vty_out(vty, "  class-900 %d%s", set->class_900,
+                               VTY_NEWLINE);
        if (sup->gsm_850)
-               vty_out(vty, "  class-850 %d%s", set->class_850, VTY_NEWLINE);
+               if (!hide_default || sup->class_850 != set->class_850)
+                       vty_out(vty, "  class-850 %d%s", set->class_850,
+                               VTY_NEWLINE);
        if (sup->gsm_480 || sup->gsm_450)
-               vty_out(vty, "  class-400 %d%s", set->class_400, VTY_NEWLINE);
+               if (!hide_default || sup->class_400 != set->class_400)
+                       vty_out(vty, "  class-400 %d%s", set->class_400,
+                               VTY_NEWLINE);
        if (sup->dcs)
-               vty_out(vty, "  class-dcs %d%s", set->class_dcs, VTY_NEWLINE);
+               if (!hide_default || sup->class_dcs != set->class_dcs)
+                       vty_out(vty, "  class-dcs %d%s", set->class_dcs,
+                               VTY_NEWLINE);
        if (sup->pcs)
-               vty_out(vty, "  class-pcs %d%s", set->class_pcs, VTY_NEWLINE);
-       switch (set->ch_cap) {
-       case GSM_CAP_SDCCH:
-               vty_out(vty, "  channel-capability sdcch%s", VTY_NEWLINE);
-               break;
-       case GSM_CAP_SDCCH_TCHF:
-               vty_out(vty, "  channel-capability sdcch+tchf%s", VTY_NEWLINE);
-               break;
-       case GSM_CAP_SDCCH_TCHF_TCHH:
-               vty_out(vty, "  channel-capability sdcch+tchf+tchh%s",
-                       VTY_NEWLINE);
-               break;
+               if (!hide_default || sup->class_pcs != set->class_pcs)
+                       vty_out(vty, "  class-pcs %d%s", set->class_pcs,
+                               VTY_NEWLINE);
+       if (!hide_default || sup->ch_cap != set->ch_cap) {
+               switch (set->ch_cap) {
+               case GSM_CAP_SDCCH:
+                       vty_out(vty, "  channel-capability sdcch%s",
+                               VTY_NEWLINE);
+                       break;
+               case GSM_CAP_SDCCH_TCHF:
+                       vty_out(vty, "  channel-capability sdcch+tchf%s",
+                               VTY_NEWLINE);
+                       break;
+               case GSM_CAP_SDCCH_TCHF_TCHH:
+                       vty_out(vty, "  channel-capability sdcch+tchf+tchh%s",
+                               VTY_NEWLINE);
+                       break;
+               }
        }
        SUP_WRITE(full_v1, "full-speech-v1");
        SUP_WRITE(full_v2, "full-speech-v2");
        SUP_WRITE(full_v3, "full-speech-v3");
        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);
+       if (!hide_default || sup->min_rxlev_db != set->min_rxlev_db)
+               vty_out(vty, "  min-rxlev %d%s", set->min_rxlev_db,
+                       VTY_NEWLINE);
+       if (!hide_default || sup->dsc_max != set->dsc_max)
+               vty_out(vty, "  dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
+       if (!hide_default || set->skip_max_per_band)
+               vty_out(vty, "  %skip-max-per-band%s",
+                       (set->skip_max_per_band) ? "" : "no ", 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);
        switch (set->test_ki_type) {
        case GSM_SIM_KEY_XOR:
-               vty_out(vty, "  ki xor %s%s", osmo_hexdump(set->test_ki, 12),
-                       VTY_NEWLINE);
+               vty_out(vty, "  ki xor %s%s",
+                       osmo_hexdump(set->test_ki, 12), VTY_NEWLINE);
                break;
        case GSM_SIM_KEY_COMP128:
-               vty_out(vty, "  ki comp128 %s%s", osmo_hexdump(set->test_ki, 16),
-                       VTY_NEWLINE);
+               vty_out(vty, "  ki comp128 %s%s",
+                       osmo_hexdump(set->test_ki, 16), VTY_NEWLINE);
                break;
        }
-       vty_out(vty, "  %sbarred-access%s", (set->test_barr) ? "" : "no ",
-               VTY_NEWLINE);
+       if (!hide_default || set->test_barr)
+               vty_out(vty, "  %sbarred-access%s",
+                       (set->test_barr) ? "" : "no ", VTY_NEWLINE);
        if (set->test_rplmn_valid) {
                vty_out(vty, "  rplmn %s %s",
                        gsm_print_mcc(set->test_rplmn_mcc),
@@ -1208,10 +1363,14 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
                        vty_out(vty, " 0x%08x", set->test_tmsi);
                vty_out(vty, "%s", VTY_NEWLINE);
        } else
-               vty_out(vty, "  no rplmn%s", VTY_NEWLINE);
-       vty_out(vty, "  hplmn-search %s%s", (set->test_always) ? "everywhere"
-                       : "foreign-country", VTY_NEWLINE);
+               if (!hide_default)
+                       vty_out(vty, "  no rplmn%s", VTY_NEWLINE);
+       if (!hide_default || set->test_always)
+               vty_out(vty, "  hplmn-search %s%s",
+                       (set->test_always) ? "everywhere" : "foreign-country",
+                       VTY_NEWLINE);
        vty_out(vty, " exit%s", VTY_NEWLINE);
+       /* no shutdown must be written to config, because shutdown is default */
        vty_out(vty, " %sshutdown%s", (ms->shutdown) ? "" : "no ",
                VTY_NEWLINE);
        vty_out(vty, "exit%s", VTY_NEWLINE);
@@ -1234,6 +1393,10 @@ static int config_write(struct vty *vty)
        vty_out(vty, "%sgps enable%s", (g.enable) ? "" : "no ", VTY_NEWLINE);
        vty_out(vty, "!%s", VTY_NEWLINE);
 
+       vty_out(vty, "%shide-default%s", (hide_default) ? "": "no ",
+               VTY_NEWLINE);
+       vty_out(vty, "!%s", VTY_NEWLINE);
+
        llist_for_each_entry(ms, &ms_list, entity)
                config_write_ms(vty, ms);
 
@@ -1279,8 +1442,8 @@ DEFUN(cfg_ms_sap, cfg_ms_sap_cmd, "sap-socket PATH",
 }
 
 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
-       "Set SIM card type when powering on\nNo SIM interted\n"
-       "Use SIM from reader\nTest SIM inserted")
+       "Set SIM card to attach when powering on\nAttach no SIM\n"
+       "Attach SIM from reader\nAttach bulit in test SIM")
 {
        struct osmocom_ms *ms = vty->index;
        struct gsm_settings *set = &ms->settings;
@@ -1300,7 +1463,8 @@ DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
                return CMD_WARNING;
        }
 
-       vty_restart(vty, ms);
+       vty_restart_if_started(vty, ms);
+
        return CMD_SUCCESS;
 }
 
@@ -1312,21 +1476,20 @@ DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
        struct gsm_settings *set = &ms->settings;
        struct msgb *nmsg;
 
-       if (!ms->plmn.state) {
+       if (!ms->started) {
                if (argv[0][0] == 'a')
                        set->plmn_mode = PLMN_MODE_AUTO;
                else
                        set->plmn_mode = PLMN_MODE_MANUAL;
-
-               return CMD_SUCCESS;
+       } else {
+               if (argv[0][0] == 'a')
+                       nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
+               else
+                       nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
+               if (!nmsg)
+                       return CMD_WARNING;
+               gsm322_plmn_sendmsg(ms, nmsg);
        }
-       if (argv[0][0] == 'a')
-               nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
-       else
-               nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
-       if (!nmsg)
-               return CMD_WARNING;
-       gsm322_plmn_sendmsg(ms, nmsg);
 
        return CMD_SUCCESS;
 }
@@ -1363,7 +1526,6 @@ DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
 
        set->imei_random = 0;
 
-       vty_restart(vty, ms);
        return CMD_SUCCESS;
 }
 
@@ -1376,7 +1538,6 @@ DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
 
        set->imei_random = atoi(argv[0]);
 
-       vty_restart(vty, ms);
        return CMD_SUCCESS;
 }
 
@@ -1767,6 +1928,33 @@ DEFUN(cfg_no_abbrev, cfg_ms_no_abbrev_cmd, "no abbrev [ABBREVIATION]",
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_ms_neighbour, cfg_ms_neighbour_cmd, "neighbour-measurement",
+       "Allow neighbour cell measurement in idle mode")
+{
+       struct osmocom_ms *ms = vty->index;
+       struct gsm_settings *set = &ms->settings;
+
+       set->no_neighbour = 0;
+
+       vty_restart_if_started(vty, ms);
+
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_no_neighbour, cfg_ms_no_neighbour_cmd, "no neighbour-measurement",
+       NO_STR "Do not allow neighbour cell measurement in idle mode")
+{
+       struct osmocom_ms *ms = vty->index;
+       struct gsm_settings *set = &ms->settings;
+
+       set->no_neighbour = 1;
+
+       vty_restart_if_started(vty, ms);
+
+       return CMD_SUCCESS;
+}
+
 static int config_write_dummy(struct vty *vty)
 {
        return CMD_SUCCESS;
@@ -1856,7 +2044,7 @@ SUP_DI(cfg_ms_sup_no_a5_5, cfg_ms_sup_no_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
 SUP_EN(cfg_ms_sup_a5_6, cfg_ms_sup_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
 SUP_DI(cfg_ms_sup_no_a5_6, cfg_ms_sup_no_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
 SUP_EN(cfg_ms_sup_a5_7, cfg_ms_sup_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
-SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 1);
+SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
 SUP_EN(cfg_ms_sup_p_gsm, cfg_ms_sup_p_gsm_cmd, p_gsm, "p-gsm", "P-GSM (900)",
        1);
 SUP_DI(cfg_ms_sup_no_p_gsm, cfg_ms_sup_no_p_gsm_cmd, p_gsm, "p-gsm",
@@ -1869,22 +2057,22 @@ SUP_EN(cfg_ms_sup_r_gsm, cfg_ms_sup_r_gsm_cmd, r_gsm, "r-gsm", "R-GSM (850)",
        1);
 SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
        "R-GSM (850)", 1);
-SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
-SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
+SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 1);
+SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 1);
 SUP_EN(cfg_ms_sup_gsm_850, cfg_ms_sup_gsm_850_cmd, gsm_850, "gsm-850",
-       "GSM 850", 0);
+       "GSM 850", 1);
 SUP_DI(cfg_ms_sup_no_gsm_850, cfg_ms_sup_no_gsm_850_cmd, gsm_850, "gsm-850",
-       "GSM 850", 0);
-SUP_EN(cfg_ms_sup_pcs, cfg_ms_sup_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
-SUP_DI(cfg_ms_sup_no_pcs, cfg_ms_sup_no_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
+       "GSM 850", 1);
+SUP_EN(cfg_ms_sup_pcs, cfg_ms_sup_pcs_cmd, pcs, "pcs", "PCS (1900)", 1);
+SUP_DI(cfg_ms_sup_no_pcs, cfg_ms_sup_no_pcs_cmd, pcs, "pcs", "PCS (1900)", 1);
 SUP_EN(cfg_ms_sup_gsm_480, cfg_ms_sup_gsm_480_cmd, gsm_480, "gsm-480",
-       "GSM 480", 0);
+       "GSM 480", 1);
 SUP_DI(cfg_ms_sup_no_gsm_480, cfg_ms_sup_no_gsm_480_cmd, gsm_480, "gsm-480",
-       "GSM 480", 0);
+       "GSM 480", 1);
 SUP_EN(cfg_ms_sup_gsm_450, cfg_ms_sup_gsm_450_cmd, gsm_450, "gsm-450",
-       "GSM 450", 0);
+       "GSM 450", 1);
 SUP_DI(cfg_ms_sup_no_gsm_450, cfg_ms_sup_no_gsm_450_cmd, gsm_450, "gsm-450",
-       "GSM 450", 0);
+       "GSM 450", 1);
 
 DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
        "Select power class for GSM 900\n"
@@ -1973,7 +2161,7 @@ DEFUN(cfg_ms_sup_class_pcs, cfg_ms_sup_class_pcs_cmd, "class-pcs (1|2|3)",
        "Select power class for PCS 1900\n"
        "1 Watt\n"
        "0.25 Watts\n"
-       "4 Watts")
+       "2 Watts")
 {
        struct osmocom_ms *ms = vty->index;
        struct gsm_settings *set = &ms->settings;
@@ -2011,9 +2199,9 @@ DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd, "channel-capability "
                return CMD_WARNING;
        }
 
-       if (ch_cap != set->ch_cap
+       if (ms->started && ch_cap != set->ch_cap
         && (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
-               vty_restart(vty, ms);
+               vty_restart_if_started(vty, ms);
 
        set->ch_cap = ch_cap;
 
@@ -2067,6 +2255,30 @@ DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_ms_sup_skip_max_per_band, cfg_ms_sup_skip_max_per_band_cmd,
+       "skip-max-per-band",
+       "Scan all frequencies per band, not only a maximum number")
+{
+       struct osmocom_ms *ms = vty->index;
+       struct gsm_settings *set = &ms->settings;
+
+       set->skip_max_per_band = 1;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_sup_no_skip_max_per_band, cfg_ms_sup_no_skip_max_per_band_cmd,
+       "no skip-max-per-band",
+       NO_STR "Scan only a maximum number of frequencies per band")
+{
+       struct osmocom_ms *ms = vty->index;
+       struct gsm_settings *set = &ms->settings;
+
+       set->skip_max_per_band = 0;
+
+       return CMD_SUCCESS;
+}
+
 /* per testsim config */
 DEFUN(cfg_ms_testsim, cfg_ms_testsim_cmd, "test-sim",
        "Configure test SIM emulation")
@@ -2090,7 +2302,8 @@ DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
 
        strcpy(set->test_imsi, argv[0]);
 
-       vty_restart(vty, ms);
+       vty_restart_if_started(vty, ms);
+
        return CMD_SUCCESS;
 }
 
@@ -2182,7 +2395,8 @@ DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
 
        set->test_rplmn_valid = 0;
 
-       vty_restart(vty, ms);
+       vty_restart_if_started(vty, ms);
+
        return CMD_SUCCESS;
 }
 
@@ -2218,7 +2432,8 @@ DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC [LAC] [TMSI]",
        else
                set->test_tmsi = 0xffffffff;
 
-       vty_restart(vty, ms);
+       vty_restart_if_started(vty, ms);
+
        return CMD_SUCCESS;
 }
 
@@ -2239,7 +2454,8 @@ DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-coun
                break;
        }
 
-       vty_restart(vty, ms);
+       vty_restart_if_started(vty, ms);
+
        return CMD_SUCCESS;
 }
 
@@ -2385,6 +2601,7 @@ int ms_vty_init(void)
        install_element_ve(&show_support_cmd);
        install_element_ve(&show_cell_cmd);
        install_element_ve(&show_cell_si_cmd);
+       install_element_ve(&show_nbcells_cmd);
        install_element_ve(&show_ba_cmd);
        install_element_ve(&show_forb_la_cmd);
        install_element_ve(&show_forb_plmn_cmd);
@@ -2407,6 +2624,8 @@ int ms_vty_init(void)
        install_element(ENABLE_NODE, &call_cmd);
        install_element(ENABLE_NODE, &call_retr_cmd);
        install_element(ENABLE_NODE, &call_dtmf_cmd);
+       install_element(ENABLE_NODE, &test_reselection_cmd);
+       install_element(ENABLE_NODE, &delete_forbidden_plmn_cmd);
 
 #ifdef _HAVE_GPSD
        install_element(CONFIG_NODE, &cfg_gps_host_cmd);
@@ -2416,6 +2635,9 @@ int ms_vty_init(void)
        install_element(CONFIG_NODE, &cfg_gps_enable_cmd);
        install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
 
+       install_element(CONFIG_NODE, &cfg_hide_default_cmd);
+       install_element(CONFIG_NODE, &cfg_no_hide_default_cmd);
+
        install_element(CONFIG_NODE, &cfg_ms_cmd);
        install_element(CONFIG_NODE, &cfg_ms_create_cmd);
        install_element(CONFIG_NODE, &cfg_ms_rename_cmd);
@@ -2459,6 +2681,8 @@ int ms_vty_init(void)
        install_element(MS_NODE, &cfg_ms_abbrev_cmd);
        install_element(MS_NODE, &cfg_ms_no_abbrev_cmd);
        install_element(MS_NODE, &cfg_ms_testsim_cmd);
+       install_element(MS_NODE, &cfg_ms_neighbour_cmd);
+       install_element(MS_NODE, &cfg_ms_no_neighbour_cmd);
        install_element(MS_NODE, &cfg_ms_support_cmd);
        install_node(&support_node, config_write_dummy);
        install_default(SUPPORT_NODE);
@@ -2516,6 +2740,8 @@ int ms_vty_init(void)
        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_element(SUPPORT_NODE, &cfg_ms_sup_skip_max_per_band_cmd);
+       install_element(SUPPORT_NODE, &cfg_ms_sup_no_skip_max_per_band_cmd);
        install_node(&testsim_node, config_write_dummy);
        install_default(TESTSIM_NODE);
        install_element(TESTSIM_NODE, &ournode_exit_cmd);