Review at  https://gerrit.osmocom.org/6097

rsl: do not allow MODE MODIFY request with unsupp. codec/rate

When the BSC sends a MODE MODIFY request with an unsupported
codec, the BTS must respond with a negative acknowledge.
Currently the codec parameter is not checked at all, which may
lead into malfunction or crash of the BTS.

- Introduce a mechanism to check the codec/rate against a
  table that is set up in the phy specific code.

- Add tables with supported codec/rate combinations for
  octphy, sysmobts, and trx.

Change-Id: Id9b222b7ab19ece90591718bc562b3a8c5e02023
Related: SYS#3212
---
M include/osmo-bts/bts.h
M include/osmo-bts/gsm_data.h
M src/common/bts.c
M src/common/rsl.c
M src/osmo-bts-octphy/l1_if.c
M src/osmo-bts-sysmo/main.c
M src/osmo-bts-trx/main.c
M tests/misc/misc_test.c
8 files changed, 106 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/97/6097/1

diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 9e16e05..2f63e37 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -45,5 +45,8 @@
 
 int bts_main(int argc, char **argv);
 
+int bts_supports_cm(struct gsm_bts_role_bts *bts,
+                   enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm);
+
 #endif /* _BTS_H */
 
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index dcffcf6..853b445 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -33,6 +33,11 @@
        struct pcu_sock_state *pcu_state;
 };
 
+struct bts_cm {
+       enum gsm_phys_chan_config pchan;
+       enum gsm48_chan_mode cm;
+};
+
 /* data structure for BTS related data specific to the BTS role */
 struct gsm_bts_role_bts {
        struct {
@@ -89,6 +94,7 @@
        bool rtp_jitter_adaptive;
        struct {
                uint8_t ciphers;        /* flags A5/1==0x1, A5/2==0x2, 
A5/3==0x4 */
+               const struct bts_cm *cm; /* Table with supp. ch rate/mode 
combinations */
        } support;
        struct {
                uint8_t tc4_ctr;
@@ -146,4 +152,6 @@
 
 bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
 
+int bts_model_check_cm_mode(enum gsm_phys_chan_config pchan, enum 
gsm48_chan_mode cm);
+
 #endif /* _GSM_DATA_H */
diff --git a/src/common/bts.c b/src/common/bts.c
index 6747f50..31afba4 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -675,3 +675,33 @@
 
        return &btsb->gsm_time;
 }
+
+int bts_supports_cm(struct gsm_bts_role_bts *bts,
+                   enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm)
+{
+       const struct bts_cm *supported;
+       int i;
+
+       supported = bts->support.cm;
+
+       /* Check if we got a list with supported codec, if not, no list has
+        * been configured yet for that BTS. In that case we will just skip
+        * and accept any combination */
+       if (supported == NULL)
+               return 1;
+
+       for (i = 0;; i++) {
+               /* If we manage to find the given combination in the list,
+                * we know that the pchan/cm combination is supported */
+               if (supported[i].pchan == pchan && supported[i].cm == cm)
+                       return 1;
+
+               /* When we hit the terminator, we know that the given
+                * pchan/cm combination is not supported because it
+                * is not in the list. */
+               if (supported[i].pchan == _GSM_PCHAN_MAX)
+                       return 0;
+       }
+
+       return 0;
+}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 3d0993c..2eb0db1 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -1278,6 +1278,7 @@
        struct gsm_lchan *lchan = msg->lchan;
        struct rsl_ie_chan_mode *cm;
        struct tlv_parsed tp;
+       struct gsm_bts_role_bts *btsb = bts_role_bts(lchan->ts->trx->bts);
 
        rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
 
@@ -1289,6 +1290,11 @@
        cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE);
        lchan_tchmode_from_cmode(lchan, cm);
 
+       if (bts_supports_cm(btsb, lchan->ts->pchan, lchan->tch_mode) != 1) {
+               LOGP(DRSL, LOGL_ERROR, "invalid mode/codec instructed by BSC, 
check BSC configuration.\n");
+               return rsl_tx_mode_modif_nack(lchan, RSL_ERR_SERV_OPT_UNAVAIL);
+       }
+
        /* 9.3.7 Encryption Information */
        if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) {
                uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO);
diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c
index fce3484..dde993d 100644
--- a/src/osmo-bts-octphy/l1_if.c
+++ b/src/osmo-bts-octphy/l1_if.c
@@ -76,6 +76,14 @@
 /* timeout until which we expect PHY to respond */
 #define CMD_TIMEOUT            5
 
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+       { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+       { _GSM_PCHAN_MAX, 0 }
+};
+
 /* allocate a msgb for a Layer1 primitive */
 struct msgb *l1p_msgb_alloc(void)
 {
@@ -776,6 +784,7 @@
        bts->variant = BTS_OSMO_OCTPHY;
        btsb = bts_role_bts(bts);
        btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
+       btsb->support.cm = bts_model_supported_cm;
 
        /* FIXME: what is the nominal transmit power of the PHY/board? */
        bts->c0->nominal_power = 15;
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index ce12d63..f52ecdd 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -55,6 +55,17 @@
 #include "hw_misc.h"
 #include "oml_router.h"
 
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+       { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR},
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+       { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+       { _GSM_PCHAN_MAX, 0 }
+};
+
 int bts_model_init(struct gsm_bts *bts)
 {
        struct gsm_bts_role_bts *btsb;
@@ -65,6 +76,7 @@
        bts->variant = BTS_OSMO_SYSMO;
        btsb = bts_role_bts(bts);
        btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
+       btsb->support.cm = bts_model_supported_cm;
 
        rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
        if (rc < 0) {
diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c
index a1eb686..973a611 100644
--- a/src/osmo-bts-trx/main.c
+++ b/src/osmo-bts-trx/main.c
@@ -59,6 +59,17 @@
 #include "l1_if.h"
 #include "trx_if.h"
 
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+       { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR},
+       { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+       { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+       { _GSM_PCHAN_MAX, 0 }
+};
+
 /* dummy, since no direct dsp support */
 uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
 {
@@ -101,6 +112,7 @@
 
        bts->variant = BTS_OSMO_TRX;
        btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
+       btsb->support.cm = bts_model_supported_cm;
 
        /* FIXME: this needs to be overridden with the real hardrware
         * value */
diff --git a/tests/misc/misc_test.c b/tests/misc/misc_test.c
index c2918fb..00744a6 100644
--- a/tests/misc/misc_test.c
+++ b/tests/misc/misc_test.c
@@ -157,6 +157,31 @@
        }
 }
 
+static const struct bts_cm bts_model_supported_cm[] = {
+       {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+       {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+       {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+       {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+       {_GSM_PCHAN_MAX, 0}
+};
+
+static void test_bts_supports_cm(void)
+{
+       struct gsm_bts_role_bts bts;
+       bts.support.cm = bts_model_supported_cm;
+
+       OSMO_ASSERT(bts_supports_cm
+                   (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1) == 1);
+       OSMO_ASSERT(bts_supports_cm
+                   (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1) == 1);
+       OSMO_ASSERT(bts_supports_cm
+                   (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR) == 0);
+       OSMO_ASSERT(bts_supports_cm
+                   (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR) == 1);
+       OSMO_ASSERT(bts_supports_cm
+                   (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR) == 1);
+}
+
 int main(int argc, char **argv)
 {
        bts_log_init(NULL);
@@ -164,5 +189,6 @@
        test_sacch_get();
        test_msg_utils_ipa();
        test_msg_utils_oml();
+       test_bts_supports_cm();
        return EXIT_SUCCESS;
 }

-- 
To view, visit https://gerrit.osmocom.org/6097
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id9b222b7ab19ece90591718bc562b3a8c5e02023
Gerrit-PatchSet: 1
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: dexter <pma...@sysmocom.de>

Reply via email to