summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-05-27 14:10:40 +0200
committerHarald Welte <laforge@gnumonks.org>2017-05-27 15:55:11 +0200
commit2abd5e1663f34cee545edcc9e4592ec45b6c0c1e (patch)
treea4793d2a5221b3730c3d5256e4fe427593527c30
parent645eb622832671a2256987f1857da86cd50a9eea (diff)
bsc_vty.c: Add command for manual [de]actiovation of logical channels
Sometimes it is useful to manually activate (or decativate) a given logical channel from the VTY. Doing this on the BSC (rather than the BTS) ensures that the BSC knows that this timeslot / channel is allocated and there is no risk to have clashes between the BSC "owning" the resources and the BTS allocating some by itself. Change-Id: I44fc3904678eb48bd3ab1a3da8c0c265fa082e0d
-rw-r--r--openbsc/src/libbsc/bsc_vty.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index b5ea8d173..3ad0b2026 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -3916,6 +3916,124 @@ DEFUN(pdch_act, pdch_act_cmd,
}
+/* determine the logical channel type based on the physical channel type */
+static int lchan_type_by_pchan(enum gsm_phys_chan_config pchan)
+{
+ switch (pchan) {
+ case GSM_PCHAN_TCH_F:
+ return GSM_LCHAN_TCH_F;
+ case GSM_PCHAN_TCH_H:
+ return GSM_LCHAN_TCH_H;
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
+ case GSM_PCHAN_CCCH_SDCCH4:
+ case GSM_PCHAN_CCCH_SDCCH4_CBCH:
+ return GSM_LCHAN_SDCCH;
+ default:
+ return -1;
+ }
+}
+
+/* configure the lchan for a single AMR mode (as specified) */
+static int lchan_set_single_amr_mode(struct gsm_lchan *lchan, uint8_t amr_mode)
+{
+ struct amr_multirate_conf mr;
+ struct gsm48_multi_rate_conf *mr_conf;
+ mr_conf = (struct gsm48_multi_rate_conf *) &mr.gsm48_ie;
+
+ if (amr_mode > 7)
+ return -1;
+
+ memset(&mr, 0, sizeof(mr));
+ mr_conf->ver = 1;
+ /* bit-mask of supported modes, only one bit is set. Reflects
+ * Figure 10.5.2.47a where there are no thershold and only a
+ * single mode */
+ mr.gsm48_ie[1] = 1 << amr_mode;
+
+ mr.ms_mode[0].mode = amr_mode;
+ mr.bts_mode[0].mode = amr_mode;
+
+ /* encode this configuration into the lchan for both uplink and
+ * downlink direction */
+ gsm48_multirate_config(lchan->mr_ms_lv, &mr, mr.ms_mode);
+ gsm48_multirate_config(lchan->mr_bts_lv, &mr, mr.bts_mode);
+
+ return 0;
+}
+
+/* Debug/Measurement command to activate a given logical channel
+ * manually in a given mode/codec. This is useful for receiver
+ * performance testing (FER/RBER/...) */
+DEFUN(lchan_act, lchan_act_cmd,
+ "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7> (activate|deactivate) (hr|fr|efr|amr) [<0-7>]",
+ "BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
+ "TRX Timeslot\n" "Timeslot Number\n" "Sub-Slot Number\n" "Sub-Slot Number\n"
+ "Manual Channel Activation (e.g. for BER test)\n"
+ "Manual Channel Deactivation (e.g. for BER test)\n"
+ "Half-Rate v1\n" "Full-Rate\n" "Enhanced Full Rate\n" "Adaptive Multi-Rate\n" "AMR Mode\n")
+{
+ struct gsm_bts_trx_ts *ts;
+ struct gsm_lchan *lchan;
+ int ss_nr = atoi(argv[3]);
+ const char *act_str = argv[4];
+ const char *codec_str = argv[5];
+ int activate;
+
+ ts = vty_get_ts(vty, argv[0], argv[1], argv[2]);
+ if (!ts)
+ return CMD_WARNING;
+
+ lchan = &ts->lchan[ss_nr];
+
+ if (!strcmp(act_str, "activate"))
+ activate = 1;
+ else
+ activate = 0;
+
+ if (ss_nr >= ts_subslots(ts)) {
+ vty_out(vty, "%% subslot %d >= permitted %d for physical channel %s%s",
+ ss_nr, ts_subslots(ts), gsm_pchan_name(ts->pchan), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (activate) {
+ int lchan_t;
+ if (lchan->state != LCHAN_S_NONE) {
+ vty_out(vty, "%% Cannot activate: Channel busy!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ lchan_t = lchan_type_by_pchan(ts->pchan);
+ if (lchan_t < 0)
+ return CMD_WARNING;
+ /* configure the lchan */
+ lchan->type = lchan_t;
+ lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
+ if (!strcmp(codec_str, "hr") || !strcmp(codec_str, "fr"))
+ lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
+ else if (!strcmp(codec_str, "efr"))
+ lchan->tch_mode = GSM48_CMODE_SPEECH_EFR;
+ else if (!strcmp(codec_str, "amr")) {
+ int amr_mode;
+ if (argc < 7) {
+ vty_out(vty, "%% AMR requires specification of AMR mode%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ amr_mode = atoi(argv[6]);
+ lchan->tch_mode = GSM48_CMODE_SPEECH_AMR;
+ lchan_set_single_amr_mode(lchan, amr_mode);
+ }
+ vty_out(vty, "%% activating lchan %s%s", gsm_lchan_name(lchan), VTY_NEWLINE);
+ rsl_chan_activate_lchan(lchan, RSL_ACT_TYPE_INITIAL, 0);
+ rsl_ipacc_crcx(lchan);
+ /* FIXME: MDCX for RTP */
+ } else {
+ rsl_direct_rf_release(lchan);
+ }
+
+ return CMD_SUCCESS;
+}
+
extern int bsc_vty_init_extra(void);
int bsc_vty_init(struct gsm_network *network)
@@ -4113,6 +4231,7 @@ int bsc_vty_init(struct gsm_network *network)
install_element(ENABLE_NODE, &drop_bts_cmd);
install_element(ENABLE_NODE, &restart_bts_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
+ install_element(ENABLE_NODE, &lchan_act_cmd);
install_element(ENABLE_NODE, &smscb_cmd_cmd);
abis_nm_vty_init();