diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-07-10 05:13:10 +0700 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-07-12 03:52:34 +0700 |
commit | 0cfd0bbe801d86e1a3cbc08b228f9ad2521ebd08 (patch) | |
tree | 1eee8cb0dffa769bafa330530b2bd0784d92f560 | |
parent | fd8962e89144fb0af4b99199589d9f9768804640 (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.c | 21 | ||||
-rw-r--r-- | src/host/trxcon/src/sched_lchan_tchh.c | 32 | ||||
-rw-r--r-- | src/host/trxcon/src/sched_prim.c | 4 |
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 */ |