summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2023-07-10 05:13:10 +0700
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2023-07-12 03:52:34 +0700
commit0cfd0bbe801d86e1a3cbc08b228f9ad2521ebd08 (patch)
tree1eee8cb0dffa769bafa330530b2bd0784d92f560
parentfd8962e89144fb0af4b99199589d9f9768804640 (diff)
trxcon/l1sched: transmit dummy speech blocks with inverted CRC3
In case when an Uplink TCH/[FH]S frame needs to be transmitted, but there is no frame available in the Tx queue, transmit an intentionally invalid block with inverted CRC3. This will induce a BFI condition in the BTS side receiver. See also the related osmo-bts-trx patch. Change-Id: I16ff09a220da13c2c76538bc43354afc4e688794 Depends: libosmocore.git Iade3310e16b906efb6892d28f474a0d15204e861 Related: osmo-bts.git I78106802a0aa4af39859c75d29fe0e77037899fe
-rw-r--r--src/host/trxcon/src/sched_lchan_tchf.c21
-rw-r--r--src/host/trxcon/src/sched_lchan_tchh.c32
-rw-r--r--src/host/trxcon/src/sched_prim.c4
3 files changed, 39 insertions, 18 deletions
diff --git a/src/host/trxcon/src/sched_lchan_tchf.c b/src/host/trxcon/src/sched_lchan_tchf.c
index cd53c46f..0206b610 100644
--- a/src/host/trxcon/src/sched_lchan_tchf.c
+++ b/src/host/trxcon/src/sched_lchan_tchf.c
@@ -230,15 +230,20 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
*mask = *mask << 4;
lchan->prim = prim_dequeue_tchf(lchan);
- if (lchan->prim == NULL)
- lchan->prim = l1sched_lchan_prim_dummy_lapdm(lchan);
- OSMO_ASSERT(lchan->prim != NULL);
/* populate the buffer with bursts */
switch (lchan->tch_mode) {
case GSM48_CMODE_SIGN:
+ if (lchan->prim == NULL)
+ lchan->prim = l1sched_lchan_prim_dummy_lapdm(lchan);
+ /* fall-through */
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
+ if (lchan->prim == NULL) {
+ /* transmit a dummy speech block with inverted CRC3 */
+ gsm0503_tch_fr_encode(bursts_p, NULL, 0, 1);
+ goto send_burst;
+ }
rc = gsm0503_tch_fr_encode(bursts_p,
msgb_l2(lchan->prim),
msgb_l2len(lchan->prim), 1);
@@ -246,8 +251,14 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
case GSM48_CMODE_SPEECH_AMR:
{
bool amr_fn_is_cmr = !sched_tchf_ul_amr_cmi_map[br->fn % 26];
- const uint8_t *data = msgb_l2(lchan->prim);
- size_t data_len = msgb_l2len(lchan->prim);
+ const uint8_t *data = lchan->prim ? msgb_l2(lchan->prim) : NULL;
+ size_t data_len = lchan->prim ? msgb_l2len(lchan->prim) : 0;
+
+ if (lchan->prim == NULL) {
+ /* TODO: It's not clear what to do for TCH/AFS.
+ * TODO: Send dummy FACCH maybe? */
+ goto send_burst; /* send something */
+ }
if (data_len != GSM_MACBLOCK_LEN) { /* TCH/AFS: speech */
if (!l1sched_lchan_amr_prim_is_valid(lchan, amr_fn_is_cmr))
diff --git a/src/host/trxcon/src/sched_lchan_tchh.c b/src/host/trxcon/src/sched_lchan_tchh.c
index 3fa823ba..3b329cb9 100644
--- a/src/host/trxcon/src/sched_lchan_tchh.c
+++ b/src/host/trxcon/src/sched_lchan_tchh.c
@@ -382,20 +382,21 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan,
}
lchan->prim = prim_dequeue_tchh(lchan, br->fn);
- if (lchan->prim == NULL) {
- if (l1sched_tchh_facch_start(lchan->type, br->fn, 1))
- lchan->prim = l1sched_lchan_prim_dummy_lapdm(lchan);
- if (lchan->prim == NULL)
- return -ENOENT;
- }
-
- if (msgb_l2len(lchan->prim) == GSM_MACBLOCK_LEN)
- lchan->ul_facch_blocks = 6;
/* populate the buffer with bursts */
switch (lchan->tch_mode) {
case GSM48_CMODE_SIGN:
+ if (!l1sched_tchh_facch_start(lchan->type, br->fn, 1))
+ goto send_burst; /* XXX: should not happen */
+ if (lchan->prim == NULL)
+ lchan->prim = l1sched_lchan_prim_dummy_lapdm(lchan);
+ /* fall-through */
case GSM48_CMODE_SPEECH_V1:
+ if (lchan->prim == NULL) {
+ /* transmit a dummy speech block with inverted CRC3 */
+ gsm0503_tch_hr_encode(bursts_p, NULL, 0);
+ goto send_burst;
+ }
rc = gsm0503_tch_hr_encode(bursts_p,
msgb_l2(lchan->prim),
msgb_l2len(lchan->prim));
@@ -403,8 +404,14 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan,
case GSM48_CMODE_SPEECH_AMR:
{
bool amr_fn_is_cmr = !sched_tchh_ul_amr_cmi_map[br->fn % 26];
- const uint8_t *data = msgb_l2(lchan->prim);
- size_t data_len = msgb_l2len(lchan->prim);
+ const uint8_t *data = lchan->prim ? msgb_l2(lchan->prim) : NULL;
+ size_t data_len = lchan->prim ? msgb_l2len(lchan->prim) : 0;
+
+ if (lchan->prim == NULL) {
+ /* TODO: It's not clear what to do for TCH/AHS.
+ * TODO: Send dummy FACCH maybe? */
+ goto send_burst; /* send garbage */
+ }
if (data_len != GSM_MACBLOCK_LEN) { /* TCH/AHS: speech */
if (!l1sched_lchan_amr_prim_is_valid(lchan, amr_fn_is_cmr))
@@ -438,6 +445,9 @@ free_bad_msg:
return -EINVAL;
}
+ if (msgb_l2len(lchan->prim) == GSM_MACBLOCK_LEN)
+ lchan->ul_facch_blocks = 6;
+
send_burst:
/* Determine which burst should be sent */
burst = bursts_p + br->bid * 116;
diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c
index 46756750..32115608 100644
--- a/src/host/trxcon/src/sched_prim.c
+++ b/src/host/trxcon/src/sched_prim.c
@@ -349,8 +349,8 @@ int l1sched_lchan_emit_data_cnf(struct l1sched_lchan_state *lchan, uint32_t fn)
struct msgb *msg;
/* take ownership of the prim */
- OSMO_ASSERT(lchan->prim != NULL);
- msg = lchan->prim;
+ if ((msg = lchan->prim) == NULL)
+ return -ENODEV;
lchan->prim = NULL;
/* convert from DATA.req to DATA.cnf */