aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2019-04-21 05:50:35 +0700
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2019-05-09 16:22:20 +0000
commit5f9e42a891f014ce304cab041dcdc92315a4221d (patch)
tree74cedd65a0bfc643c2121d957c7695240939be3d
parent9354474b0fa3b333c8d4e27c9b6b907ccd7b5216 (diff)
osmo-bts-trx: distinguish 11-bit Access Bursts by synch. sequence
Thanks to both TC_rach_content and TC_rach_count TTCN-3 test cases, it was discovered that there are possible collisions when trying to decode a regular 8-bit Access Burst as an 11-bit one. This is exactly what we are doing in rx_rach_fn(): - calling gsm0503_rach_ext_decode_ber() first, - if it failed, falling-back to gsm0503_rach_decode_ber(). With default BSIC=63, the following 8-bit RA values are being misinterpreted as 11-bit Access Bursts: Successfully decoded 8-bit (0x00) RACH as 11-bit (0x0000): bsic=0x3f Successfully decoded 8-bit (0xbe) RACH as 11-bit (0x0388): bsic=0x3f Successfully decoded 8-bit (0xcf) RACH as 11-bit (0x0036): bsic=0x3f According to 3GPP TS 05.02, section 5.2.7, there are two alternative synch. (training) sequences for Access Bursts: TS1 & TS2. By default, TS0 synch. sequence is used, unless explicitly stated otherwise (see 3GPP TS 04.60). According to 3GPP TS 04.60, section 11.2.5a, the EGPRS capability can be indicated by the MS using one of the alternative training sequences (i.e. TS1 or TS2) and the 11-bit RACH coding scheme. In other words, knowing the synch. sequence of a received Access Burst would allow to decide whether it's extended (11-bit) or a regular (8-bit) one. As a result, we would avoid possible collisions and save some CPU power. Unfortunately, due to the limitations of the current TRXD protocol, there is no easy way to expose such information from the transceiver. A proper solution would be to extend the TRX protocol, but for now, let's do the synch. sequence detection in rx_rach_fn(). As soon as the TRX protocol is extended with info about the synch. sequence, this code would serve for the backwards-compatibility. This change makes the both TC_rach_content and TC_rach_count happy, as well as the new TC_pcu_ext_rach_content() test case aimed to verify extended (11-bit) Access Burst decoding. Related (TTCN-3) I8fe156aeac9de3dc1e71a4950821d4942ba9a253 Change-Id: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284 Related: OS#1854
-rw-r--r--src/osmo-bts-trx/scheduler_trx.c167
1 files changed, 124 insertions, 43 deletions
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index 32bdb98c..ade3cfff 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -22,6 +22,7 @@
*/
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
#include <errno.h>
#include <stdint.h>
#include <ctype.h>
@@ -709,72 +710,152 @@ send_burst:
* RX on uplink (indication to upper layer)
*/
+/* 3GPP TS 05.02, section 5.2.7 */
+#define RACH_EXT_TAIL_LEN 8
+#define RACH_SYNCH_SEQ_LEN 41
+
+enum rach_synch_seq_t {
+ RACH_SYNCH_SEQ_UNKNOWN = -1,
+ RACH_SYNCH_SEQ_TS0, /* GSM, GMSK (default) */
+ RACH_SYNCH_SEQ_TS1, /* EGPRS, 8-PSK */
+ RACH_SYNCH_SEQ_TS2, /* EGPRS, GMSK */
+ RACH_SYNCH_SEQ_NUM
+};
+
+static struct value_string rach_synch_seq_names[] = {
+ { RACH_SYNCH_SEQ_UNKNOWN, "UNKNOWN" },
+ { RACH_SYNCH_SEQ_TS0, "TS0: GSM, GMSK" },
+ { RACH_SYNCH_SEQ_TS1, "TS1: EGPRS, 8-PSK" },
+ { RACH_SYNCH_SEQ_TS2, "TS2: EGPRS, GMSK" },
+ { 0, NULL },
+};
+
+static enum rach_synch_seq_t rach_get_synch_seq(sbit_t *bits, int *best_score)
+{
+ sbit_t *synch_seq_burst = bits + RACH_EXT_TAIL_LEN;
+ enum rach_synch_seq_t seq = RACH_SYNCH_SEQ_TS0;
+ int score[RACH_SYNCH_SEQ_NUM] = { 0 };
+ int max_score = INT_MIN;
+ int i, j;
+
+ /* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)", synch. sequence bits */
+ static const char synch_seq_ref[RACH_SYNCH_SEQ_NUM][RACH_SYNCH_SEQ_LEN] = {
+ [RACH_SYNCH_SEQ_TS0] = "01001011011111111001100110101010001111000",
+ [RACH_SYNCH_SEQ_TS1] = "01010100111110001000011000101111001001101",
+ [RACH_SYNCH_SEQ_TS2] = "11101111001001110101011000001101101110111",
+ };
+
+ /* Get a multiplier for j-th bit of i-th synch. sequence */
+#define RACH_SYNCH_SEQ_MULT \
+ (synch_seq_ref[i][j] == '1' ? -1 : 1)
+
+ /* For each synch. sequence, count the bit match score. Since we deal with
+ * soft-bits (-127...127), we sum the absolute values of matching ones,
+ * and subtract the absolute values of different ones, so the resulting
+ * score is more accurate than it could be with hard-bits. */
+ for (i = 0; i < RACH_SYNCH_SEQ_NUM; i++) {
+ for (j = 0; j < RACH_SYNCH_SEQ_LEN; j++)
+ score[i] += RACH_SYNCH_SEQ_MULT * synch_seq_burst[j];
+
+ /* Keep the maximum value updated */
+ if (score[i] > max_score) {
+ max_score = score[i];
+ seq = i;
+ }
+ }
+
+ /* Calculate an approximate level of our confidence */
+ if (best_score != NULL)
+ *best_score = max_score;
+
+ /* At least 1/3 of a synch. sequence shall match */
+ if (max_score < (127 * RACH_SYNCH_SEQ_LEN / 3))
+ return RACH_SYNCH_SEQ_UNKNOWN;
+
+ return seq;
+}
+
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256)
{
- uint8_t chan_nr;
struct osmo_phsap_prim l1sap;
int n_errors, n_bits_total;
- bool is_11bit = true;
uint16_t ra11;
uint8_t ra;
- int rc = 1;
-
- chan_nr = trx_chan_desc[chan].chan_nr | tn;
+ int rc;
- LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received RACH toa=%d\n", toa256);
+ /* It would be great if the transceiver were doing some kind of tagging,
+ * whether it is extended (11-bit) RACH or not. We would not need to guess
+ * it here. For now, let's try to correlate the synch. sequence of a received
+ * Access Burst with the known ones (3GPP TS 05.02, section 5.2.7), and
+ * fall-back to the default TS0 if it fails. This would save some CPU
+ * power, and what is more important - prevent possible collisions. */
+ enum rach_synch_seq_t synch_seq = RACH_SYNCH_SEQ_TS0;
+ int best_score = 127 * RACH_SYNCH_SEQ_LEN;
+
+ /* Handover RACH cannot be extended (11-bit) */
+ if (chan == TRXC_RACH)
+ synch_seq = rach_get_synch_seq(bits, &best_score);
+
+ LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn,
+ "Received RACH (%s; match=%.1f%%) toa=%d\n",
+ get_value_string(rach_synch_seq_names, synch_seq),
+ best_score * 100.0 / (127 * RACH_SYNCH_SEQ_LEN),
+ toa256);
+
+ /* Compose a new L1SAP primitive */
+ memset(&l1sap, 0x00, sizeof(l1sap));
+ osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, NULL);
+ l1sap.u.rach_ind.chan_nr = trx_chan_desc[chan].chan_nr | tn;
+ l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256 / 256 : 0;
+ l1sap.u.rach_ind.acc_delay_256bits = toa256;
+ l1sap.u.rach_ind.rssi = rssi;
+ l1sap.u.rach_ind.fn = fn;
- if (chan == TRXC_RACH) /* Attempt to decode as extended (11-bit) RACH first */
- rc = gsm0503_rach_ext_decode_ber(&ra11, bits + 8 + 41,
+ /* Decode RACH depending on its synch. sequence */
+ switch (synch_seq) {
+ case RACH_SYNCH_SEQ_TS1:
+ case RACH_SYNCH_SEQ_TS2:
+ rc = gsm0503_rach_ext_decode_ber(&ra11, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,
l1t->trx->bts->bsic, &n_errors, &n_bits_total);
- if (rc) {
- /* Indicate non-extended RACH */
- is_11bit = false;
-
- /* Fall-back to the normal RACH decoding */
- rc = gsm0503_rach_decode_ber(&ra, bits + 8 + 41,
- l1t->trx->bts->bsic, &n_errors, &n_bits_total);
if (rc) {
- LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad AB frame\n");
+ LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");
return 0;
}
- }
- /* compose primitive */
- /* generate prim */
- memset(&l1sap, 0, sizeof(l1sap));
- osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION,
- NULL);
- l1sap.u.rach_ind.chan_nr = chan_nr;
- l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256/256 : 0;
- l1sap.u.rach_ind.fn = fn;
- l1sap.u.rach_ind.rssi = rssi;
- l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);
- l1sap.u.rach_ind.acc_delay_256bits = toa256;
+ if (synch_seq == RACH_SYNCH_SEQ_TS1)
+ l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_1;
+ else
+ l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_2;
- if (is_11bit) {
l1sap.u.rach_ind.is_11bit = 1;
l1sap.u.rach_ind.ra = ra11;
- l1sap.u.rach_ind.burst_type = BSIC2BCC(l1t->trx->bts->bsic);
- switch (l1sap.u.rach_ind.burst_type) {
- case GSM_L1_BURST_TYPE_ACCESS_0:
- case GSM_L1_BURST_TYPE_ACCESS_1:
- case GSM_L1_BURST_TYPE_ACCESS_2:
- break;
- default:
- LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn,
- "Received RACH frame with unexpected TSC %u, "
- "forcing default %u\n", l1sap.u.rach_ind.burst_type,
- GSM_L1_BURST_TYPE_ACCESS_0);
- l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;
+ break;
+
+ case RACH_SYNCH_SEQ_TS0:
+ default:
+ /* Fall-back to the default TS0 if needed */
+ if (synch_seq != RACH_SYNCH_SEQ_TS0) {
+ LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Falling-back to the default TS0\n");
+ synch_seq = RACH_SYNCH_SEQ_TS0;
}
- } else {
+
+ rc = gsm0503_rach_decode_ber(&ra, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,
+ l1t->trx->bts->bsic, &n_errors, &n_bits_total);
+ if (rc) {
+ LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");
+ return 0;
+ }
+
+ l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;
l1sap.u.rach_ind.is_11bit = 0;
l1sap.u.rach_ind.ra = ra;
- l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;
+ break;
}
+ l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);
+
/* forward primitive */
l1sap_up(l1t->trx, &l1sap);