summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2022-07-31 00:12:24 +0700
committerfixeria <vyanitskiy@sysmocom.de>2022-08-09 10:21:17 +0000
commit15877ba0512fd3c535fa5ccbf0831caefc25ebf8 (patch)
tree9c1363df70ef642de32cf678a94fbadbb82da44b
parent6c67848afd20fc9bbf2d0a8e4d88fb6ee5b2511e (diff)
trxcon: allow populating global SACCH cache via L1CTL
There is a time window between activation of a dedicated channel and receipt of a L1CTL_DATA_REQ with the first RR Measurement Report, in which trxcon may need to start transmission on Uplink SACCH. In this case trxcon is using a dummy SACCH block with hard-coded L1 SACCH header values and hard-coded Measurement Results. This mimics behavior of the layer1 implementation in firmware for Calypso phones. When running the mobile application, this error can be seen: DAPP ERROR trxcon(0)[0x55ee57bee1a0]{FBSB_SEARCH}: Event TRXCON_EV_RX_DATA_IND not permitted which means that the mobile is sending L1CTL_DATA_REQ *before* establishing a dedicated channel. And this message contains an RR Measurement Report. The idea behind this is to populate the SACCH cache in advance and thus avoid sending dummy values. Let's allow the L2 apps populating SACCH cache before establishing a dedicated connection using new TRXCON_EV_UPDATE_SACCH_CACHE_REQ. Change-Id: I0f467fc07cf844cc73465f235b36ba7d00788c9f Related: OS#5635, OS#5599
-rw-r--r--src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h2
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h1
-rw-r--r--src/host/trxcon/src/l1ctl.c16
-rw-r--r--src/host/trxcon/src/sched_prim.c66
-rw-r--r--src/host/trxcon/src/sched_trx.c33
-rw-r--r--src/host/trxcon/src/trxcon_fsm.c20
6 files changed, 75 insertions, 63 deletions
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
index 3f7dae0c..04303f09 100644
--- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
@@ -374,6 +374,8 @@ struct l1sched_state {
void (*clock_cb)(struct l1sched_state *sched);
/*! List of timeslots maintained by this scheduler */
struct l1sched_ts *ts[TRX_TS_COUNT];
+ /*! SACCH cache (common for all lchans) */
+ uint8_t sacch_cache[GSM_MACBLOCK_LEN];
/*! BSIC value learned from SCH bursts */
uint8_t bsic;
/*! Logging context (used as prefix for messages) */
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
index eed3d614..2a6f7d57 100644
--- a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
@@ -25,6 +25,7 @@ enum trxcon_fsm_events {
TRXCON_EV_SET_TCH_MODE_REQ,
TRXCON_EV_SET_PHY_CONFIG_REQ,
TRXCON_EV_TX_ACCESS_BURST_REQ,
+ TRXCON_EV_UPDATE_SACCH_CACHE_REQ,
TRXCON_EV_DEDICATED_ESTABLISH_REQ,
TRXCON_EV_DEDICATED_RELEASE_REQ,
TRXCON_EV_TX_TRAFFIC_REQ,
diff --git a/src/host/trxcon/src/l1ctl.c b/src/host/trxcon/src/l1ctl.c
index 28086a25..4d6bed20 100644
--- a/src/host/trxcon/src/l1ctl.c
+++ b/src/host/trxcon/src/l1ctl.c
@@ -644,10 +644,18 @@ static int l1ctl_rx_dt_req(struct l1ctl_client *l1c,
"Recv %s Req (chan_nr=0x%02x, link_id=0x%02x, len=%zu)\n",
traffic ? "TRAFFIC" : "DATA", req.chan_nr, req.link_id, req.data_len);
- if (traffic)
- osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_TRAFFIC_REQ, &req);
- else
- osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_REQ, &req);
+ switch (trxcon->fi->state) {
+ case TRXCON_ST_DEDICATED:
+ if (traffic)
+ osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_TRAFFIC_REQ, &req);
+ else
+ osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_REQ, &req);
+ break;
+ default:
+ if (!traffic && req.link_id == 0x40) /* only for SACCH */
+ osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_UPDATE_SACCH_CACHE_REQ, &req);
+ /* TODO: log an error about uhnandled DATA.req / TRAFFIC.req */
+ }
msgb_free(msg);
return 0;
diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c
index 9b6d28d3..f97e5052 100644
--- a/src/host/trxcon/src/sched_prim.c
+++ b/src/host/trxcon/src/sched_prim.c
@@ -116,8 +116,7 @@ struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched,
}
/**
- * Composes a new primitive using either cached (if populated),
- * or "dummy" Measurement Report message.
+ * Composes a new primitive from cached RR Measurement Report.
*
* @param lchan lchan to assign a primitive
* @return SACCH primitive to be transmitted
@@ -125,38 +124,8 @@ struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched,
static struct l1sched_ts_prim *prim_compose_mr(struct l1sched_lchan_state *lchan)
{
struct l1sched_ts_prim *prim;
- uint8_t *mr_src_ptr;
bool cached;
- /* "Dummy" Measurement Report */
- static const uint8_t meas_rep_dummy[] = {
- /* L1 SACCH pseudo-header */
- 0x0f, 0x00,
-
- /* LAPDm header */
- 0x01, 0x03, 0x49,
-
- /* RR Management messages, Measurement Report */
- 0x06, 0x15,
-
- /* Measurement results (see 3GPP TS 44.018, section 10.5.2.20):
- * 0... .... = BA-USED: 0
- * .0.. .... = DTX-USED: DTX was not used
- * ..11 0110 = RXLEV-FULL-SERVING-CELL: -57 <= x < -56 dBm (54)
- * 0... .... = 3G-BA-USED: 0
- * .1.. .... = MEAS-VALID: The measurement results are not valid
- * ..11 0110 = RXLEV-SUB-SERVING-CELL: -57 <= x < -56 dBm (54)
- * 0... .... = SI23_BA_USED: 0
- * .000 .... = RXQUAL-FULL-SERVING-CELL: BER < 0.2%, Mean value 0.14% (0)
- * .... 000. = RXQUAL-SUB-SERVING-CELL: BER < 0.2%, Mean value 0.14% (0)
- * .... ...1 11.. .... = NO-NCELL-M: Neighbour cell information not available */
- 0x36, 0x76, 0x01, 0xc0,
-
- /* 0** -- Padding with zeroes */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
-
/* Allocate a new primitive */
prim = prim_alloc(lchan, GSM_MACBLOCK_LEN, L1SCHED_PRIM_DATA,
l1sched_lchan_desc[lchan->type].chan_nr,
@@ -167,43 +136,24 @@ static struct l1sched_ts_prim *prim_compose_mr(struct l1sched_lchan_state *lchan
cached = (lchan->sacch.mr_cache[2] != 0x00
&& lchan->sacch.mr_cache[3] != 0x00
&& lchan->sacch.mr_cache[4] != 0x00);
- if (cached) { /* Use the cached one */
- mr_src_ptr = lchan->sacch.mr_cache;
- lchan->sacch.mr_cache_usage++;
- } else { /* Use "dummy" one */
- mr_src_ptr = (uint8_t *) meas_rep_dummy;
+ if (!cached) {
+ memcpy(&lchan->sacch.mr_cache[0],
+ &lchan->ts->sched->sacch_cache[0],
+ sizeof(lchan->sacch.mr_cache));
}
/* Compose a new Measurement Report primitive */
- memcpy(prim->payload, mr_src_ptr, GSM_MACBLOCK_LEN);
-
- /**
- * Update the L1 SACCH pseudo-header (only for cached MRs)
- *
- * TODO: filling of the actual values into cached Measurement
- * Reports would break the distance spoofing feature. If it
- * were known whether the spoofing is enabled or not, we could
- * decide whether to update the cached L1 SACCH header here.
- */
- if (!cached) {
-#warning "FIXME: no direct access to trxcon->l1p.{tx_power,ta}"
-#if 0
- prim->payload[0] = lchan->ts->sched->trx->tx_power;
- prim->payload[1] = lchan->ts->sched->trx->ta;
-#endif
- }
+ memcpy(&prim->payload[0], &lchan->sacch.mr_cache[0], GSM_MACBLOCK_LEN);
/* Inform about the cache usage count */
- if (cached && lchan->sacch.mr_cache_usage > 5) {
+ if (++lchan->sacch.mr_cache_usage > 5) {
LOGP_LCHAND(lchan, LOGL_NOTICE,
"SACCH MR cache usage count=%u > 5 "
"=> ancient measurements, please fix!\n",
lchan->sacch.mr_cache_usage);
}
- LOGP_LCHAND(lchan, LOGL_NOTICE,
- "Using a %s Measurement Report\n",
- cached ? "cached" : "dummy");
+ LOGP_LCHAND(lchan, LOGL_NOTICE, "Using cached Measurement Report\n");
return prim;
}
diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c
index af2d9b39..be1f8203 100644
--- a/src/host/trxcon/src/sched_trx.c
+++ b/src/host/trxcon/src/sched_trx.c
@@ -39,6 +39,35 @@
int l1sched_log_cat_common = DLGLOBAL;
int l1sched_log_cat_data = DLGLOBAL;
+/* "Dummy" Measurement Report */
+static const uint8_t meas_rep_dummy[] = {
+ /* L1 SACCH pseudo-header */
+ 0x0f, 0x00,
+
+ /* LAPDm header */
+ 0x01, 0x03, 0x49,
+
+ /* RR Management messages, Measurement Report */
+ 0x06, 0x15,
+
+ /* Measurement results (see 3GPP TS 44.018, section 10.5.2.20):
+ * 0... .... = BA-USED: 0
+ * .0.. .... = DTX-USED: DTX was not used
+ * ..11 0110 = RXLEV-FULL-SERVING-CELL: -57 <= x < -56 dBm (54)
+ * 0... .... = 3G-BA-USED: 0
+ * .1.. .... = MEAS-VALID: The measurement results are not valid
+ * ..11 0110 = RXLEV-SUB-SERVING-CELL: -57 <= x < -56 dBm (54)
+ * 0... .... = SI23_BA_USED: 0
+ * .000 .... = RXQUAL-FULL-SERVING-CELL: BER < 0.2%, Mean value 0.14% (0)
+ * .... 000. = RXQUAL-SUB-SERVING-CELL: BER < 0.2%, Mean value 0.14% (0)
+ * .... ...1 11.. .... = NO-NCELL-M: Neighbour cell information not available */
+ 0x36, 0x76, 0x01, 0xc0,
+
+ /* 0** -- Padding with zeroes */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
static int l1sched_cfg_pchan_comb_req(struct l1sched_state *sched,
uint8_t tn, enum gsm_phys_chan_config pchan)
{
@@ -175,6 +204,8 @@ struct l1sched_state *l1sched_alloc(void *ctx, const struct l1sched_cfg *cfg, vo
.priv = priv,
};
+ memcpy(&sched->sacch_cache[0], &meas_rep_dummy[0], sizeof(meas_rep_dummy));
+
if (cfg->log_prefix == NULL)
sched->log_prefix = talloc_asprintf(sched, "l1sched[0x%p]: ", sched);
else
@@ -217,6 +248,8 @@ void l1sched_reset(struct l1sched_state *sched, bool reset_clock)
/* Stop and reset clock counter if required */
if (reset_clock)
l1sched_clck_reset(sched);
+
+ memcpy(&sched->sacch_cache[0], &meas_rep_dummy[0], sizeof(meas_rep_dummy));
}
struct l1sched_ts *l1sched_add_ts(struct l1sched_state *sched, int tn)
diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c
index 3c30565d..40d52534 100644
--- a/src/host/trxcon/src/trxcon_fsm.c
+++ b/src/host/trxcon/src/trxcon_fsm.c
@@ -71,6 +71,22 @@ static void trxcon_allstate_action(struct osmo_fsm_inst *fi,
trxcon->l1p.ta = req->timing_advance;
break;
}
+ case TRXCON_EV_UPDATE_SACCH_CACHE_REQ:
+ {
+ const struct trxcon_param_tx_traffic_data_req *req = data;
+
+ if (req->link_id != L1SCHED_CH_LID_SACCH) {
+ LOGPFSML(fi, LOGL_ERROR, "Unexpected link_id=0x%02x\n", req->link_id);
+ break;
+ }
+ if (req->data_len != GSM_MACBLOCK_LEN) {
+ LOGPFSML(fi, LOGL_ERROR, "Unexpected data length=%u\n", req->data_len);
+ break;
+ }
+
+ memcpy(&trxcon->sched->sacch_cache[0], req->data, req->data_len);
+ break;
+ }
default:
OSMO_ASSERT(0);
}
@@ -451,6 +467,7 @@ static const struct value_string trxcon_fsm_event_names[] = {
OSMO_VALUE_STRING(TRXCON_EV_SET_TCH_MODE_REQ),
OSMO_VALUE_STRING(TRXCON_EV_SET_PHY_CONFIG_REQ),
OSMO_VALUE_STRING(TRXCON_EV_TX_ACCESS_BURST_REQ),
+ OSMO_VALUE_STRING(TRXCON_EV_UPDATE_SACCH_CACHE_REQ),
OSMO_VALUE_STRING(TRXCON_EV_DEDICATED_ESTABLISH_REQ),
OSMO_VALUE_STRING(TRXCON_EV_DEDICATED_RELEASE_REQ),
OSMO_VALUE_STRING(TRXCON_EV_TX_TRAFFIC_REQ),
@@ -471,7 +488,8 @@ struct osmo_fsm trxcon_fsm_def = {
| S(TRXCON_EV_L2IF_FAILURE)
| S(TRXCON_EV_RESET_FULL_REQ)
| S(TRXCON_EV_RESET_SCHED_REQ)
- | S(TRXCON_EV_SET_PHY_CONFIG_REQ),
+ | S(TRXCON_EV_SET_PHY_CONFIG_REQ)
+ | S(TRXCON_EV_UPDATE_SACCH_CACHE_REQ),
.allstate_action = &trxcon_allstate_action,
.timer_cb = &trxcon_timer_cb,
};