summaryrefslogtreecommitdiffstats
path: root/src/host/trxcon/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/trxcon/src')
-rw-r--r--src/host/trxcon/src/sched_lchan_tchf.c69
-rw-r--r--src/host/trxcon/src/sched_lchan_tchh.c66
-rw-r--r--src/host/trxcon/src/sched_prim.c3
3 files changed, 72 insertions, 66 deletions
diff --git a/src/host/trxcon/src/sched_lchan_tchf.c b/src/host/trxcon/src/sched_lchan_tchf.c
index d11b3146..985bea48 100644
--- a/src/host/trxcon/src/sched_lchan_tchf.c
+++ b/src/host/trxcon/src/sched_lchan_tchf.c
@@ -3,7 +3,7 @@
* TDMA scheduler: handlers for DL / UL bursts on logical channels
*
* (C) 2017-2022 by Vadim Yanitskiy <axilirator@gmail.com>
- * (C) 2021-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * (C) 2021-2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -290,37 +290,49 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
/* fall-through */
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
- if (msg == NULL) {
- /* transmit a dummy speech block with inverted CRC3 */
- gsm0503_tch_fr_encode(bursts_p, NULL, 0, 1);
- goto send_burst;
- }
+ /* if msg == NULL, transmit a dummy speech block with inverted CRC3 */
rc = gsm0503_tch_fr_encode(BUFPOS(bursts_p, 0),
- msgb_l2(msg),
- msgb_l2len(msg), 1);
+ msg ? msgb_l2(msg) : NULL,
+ msg ? msgb_l2len(msg) : 0, 1);
+ /* confirm traffic sending (pass ownership of the msgb/prim) */
+ if (OSMO_LIKELY(rc == 0))
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
+ else /* unlikely: encoding failed, drop msgb/prim */
+ msgb_free(msg);
+ /* drop the other msgb/prim */
+ msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
break;
case GSM48_CMODE_SPEECH_AMR:
{
bool amr_fn_is_cmr = !sched_tchf_ul_amr_cmi_map[br->fn % 26];
- const uint8_t *data = msg ? msgb_l2(msg) : NULL;
- size_t data_len = msg ? msgb_l2len(msg) : 0;
+ unsigned int offset = 0;
if (msg != NULL && msg != msg_facch) { /* TCH/AFS: speech */
- if (!l1sched_lchan_amr_prim_is_valid(lchan, msg, amr_fn_is_cmr))
- goto free_bad_msg;
+ if (!l1sched_lchan_amr_prim_is_valid(lchan, msg, amr_fn_is_cmr)) {
+ msgb_free(msg);
+ msg_tch = NULL;
+ msg = NULL;
+ }
/* pull the AMR header - sizeof(struct amr_hdr) */
- data_len -= 2;
- data += 2;
+ offset = 2;
}
/* if msg == NULL, transmit a dummy speech block with inverted CRC6 */
rc = gsm0503_tch_afs_encode(BUFPOS(bursts_p, 0),
- data, data_len,
+ msg ? msgb_l2(msg) + offset : NULL,
+ msg ? msgb_l2len(msg) - offset : 0,
amr_fn_is_cmr,
lchan->amr.codec,
lchan->amr.codecs,
lchan->amr.ul_ft,
lchan->amr.ul_cmr);
+ /* confirm traffic sending (pass ownership of the msgb/prim) */
+ if (OSMO_LIKELY(rc == 0))
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
+ else /* unlikely: encoding failed, drop prim */
+ msgb_free(msg);
+ /* drop the other primitive */
+ msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
break;
}
/* CSD (TCH/F14.4): 14.5 kbit/s radio interface rate */
@@ -340,7 +352,7 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
/* Confirm FACCH sending (pass ownership of the msgb/prim) */
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
}
- goto send_burst;
+ break;
/* CSD (TCH/F9.6): 12.0 kbit/s radio interface rate */
case GSM48_CMODE_DATA_12k0:
if ((msg = msg_tch) != NULL) {
@@ -358,7 +370,7 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
/* Confirm FACCH sending (pass ownership of the msgb/prim) */
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
}
- goto send_burst;
+ break;
/* CSD (TCH/F4.8): 6.0 kbit/s radio interface rate */
case GSM48_CMODE_DATA_6k0:
if ((msg = msg_tch) != NULL) {
@@ -376,42 +388,33 @@ int tx_tchf_fn(struct l1sched_lchan_state *lchan,
/* Confirm FACCH sending (pass ownership of the msgb/prim) */
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
}
- goto send_burst;
+ break;
/* CSD (TCH/F2.4): 3.6 kbit/s radio interface rate */
case GSM48_CMODE_DATA_3k6:
if ((msg = msg_facch) != NULL) {
/* FACCH/F does steal a TCH/F2.4 frame completely */
- rc = gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg));
+ gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg));
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
+ msgb_free(msg_tch);
} else if ((msg = msg_tch) != NULL) {
OSMO_ASSERT(msgb_l2len(msg) == 2 * 36);
- rc = gsm0503_tch_fr24_encode(BUFPOS(bursts_p, 0), msgb_l2(msg));
+ gsm0503_tch_fr24_encode(BUFPOS(bursts_p, 0), msgb_l2(msg));
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
} else {
ubit_t idle[2 * 36];
memset(&idle[0], 0x01, sizeof(idle));
gsm0503_tch_fr24_encode(BUFPOS(bursts_p, 0), &idle[0]);
- goto send_burst;
}
break;
default:
LOGP_LCHAND(lchan, LOGL_ERROR,
"TCH mode %s is unknown or not supported\n",
gsm48_chan_mode_name(lchan->tch_mode));
- goto free_bad_msg;
- }
-
- if (rc) {
- LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n",
- msgb_l2len(msg), msgb_hexdump_l2(msg));
-free_bad_msg:
msgb_free(msg_facch);
msgb_free(msg_tch);
- return -EINVAL;
+ break;
}
- /* Confirm data / traffic sending (pass ownership of the msgb/prim) */
- l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
- msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
-
send_burst:
/* Determine which burst should be sent */
burst = BUFPOS(bursts_p, br->bid);
diff --git a/src/host/trxcon/src/sched_lchan_tchh.c b/src/host/trxcon/src/sched_lchan_tchh.c
index 0d3de003..d684976d 100644
--- a/src/host/trxcon/src/sched_lchan_tchh.c
+++ b/src/host/trxcon/src/sched_lchan_tchh.c
@@ -4,7 +4,7 @@
*
* (C) 2018-2022 by Vadim Yanitskiy <axilirator@gmail.com>
* (C) 2018 by Harald Welte <laforge@gnumonks.org>
- * (C) 2020-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * (C) 2020-2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -497,37 +497,53 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan,
msg = l1sched_lchan_prim_dummy_lapdm(lchan);
/* fall-through */
case GSM48_CMODE_SPEECH_V1:
- if (msg == NULL) {
- /* transmit a dummy speech block with inverted CRC3 */
- gsm0503_tch_hr_encode(bursts_p, NULL, 0);
- goto send_burst;
- }
+ /* if msg == NULL, transmit a dummy speech block with inverted CRC3 */
rc = gsm0503_tch_hr_encode(BUFPOS(bursts_p, 0),
- msgb_l2(msg),
- msgb_l2len(msg));
+ msg ? msgb_l2(msg) : NULL,
+ msg ? msgb_l2len(msg) : 0);
+ /* confirm traffic sending (pass ownership of the msgb/prim) */
+ if (OSMO_LIKELY(rc == 0)) {
+ if (msg && msgb_l2len(msg) == GSM_MACBLOCK_LEN)
+ lchan->ul_facch_blocks = 6;
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
+ } else /* unlikely: encoding failed, drop msgb/prim */
+ msgb_free(msg);
+ /* drop the other msgb/prim */
+ msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
break;
case GSM48_CMODE_SPEECH_AMR:
{
bool amr_fn_is_cmr = !sched_tchh_ul_amr_cmi_map[br->fn % 26];
- const uint8_t *data = msg ? msgb_l2(msg) : NULL;
- size_t data_len = msg ? msgb_l2len(msg) : 0;
+ unsigned int offset = 0;
if (msg != NULL && msg != msg_facch) { /* TCH/AHS: speech */
- if (!l1sched_lchan_amr_prim_is_valid(lchan, msg, amr_fn_is_cmr))
- goto free_bad_msg;
+ if (!l1sched_lchan_amr_prim_is_valid(lchan, msg, amr_fn_is_cmr)) {
+ msgb_free(msg);
+ msg_tch = NULL;
+ msg = NULL;
+ }
/* pull the AMR header - sizeof(struct amr_hdr) */
- data_len -= 2;
- data += 2;
+ offset = 2;
}
/* if msg == NULL, transmit a dummy speech block with inverted CRC6 */
rc = gsm0503_tch_ahs_encode(BUFPOS(bursts_p, 0),
- data, data_len,
+ msg ? msgb_l2(msg) + offset : NULL,
+ msg ? msgb_l2len(msg) - offset : 0,
amr_fn_is_cmr,
lchan->amr.codec,
lchan->amr.codecs,
lchan->amr.ul_ft,
lchan->amr.ul_cmr);
+ /* confirm traffic sending (pass ownership of the msgb/prim) */
+ if (OSMO_LIKELY(rc == 0)) {
+ if (msg && msgb_l2len(msg) == GSM_MACBLOCK_LEN)
+ lchan->ul_facch_blocks = 6;
+ l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
+ } else /* unlikely: encoding failed, drop msgb/prim */
+ msgb_free(msg);
+ /* drop the other msgb/prim */
+ msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
break;
}
/* CSD (TCH/H4.8): 6.0 kbit/s radio interface rate */
@@ -547,7 +563,7 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan,
/* Confirm FACCH sending (pass ownership of the msgb/prim) */
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
}
- goto send_burst;
+ break;
/* CSD (TCH/H2.4): 3.6 kbit/s radio interface rate */
case GSM48_CMODE_DATA_3k6:
if ((msg = msg_tch) != NULL) {
@@ -565,30 +581,16 @@ int tx_tchh_fn(struct l1sched_lchan_state *lchan,
/* Confirm FACCH sending (pass ownership of the msgb/prim) */
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
}
- goto send_burst;
+ break;
default:
LOGP_LCHAND(lchan, LOGL_ERROR,
"TCH mode %s is unknown or not supported\n",
gsm48_chan_mode_name(lchan->tch_mode));
- goto free_bad_msg;
- }
-
- if (rc) {
- LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n",
- msgb_l2len(msg), msgb_hexdump_l2(msg));
-free_bad_msg:
msgb_free(msg_facch);
msgb_free(msg_tch);
- return -EINVAL;
+ break;
}
- if (msgb_l2len(msg) == GSM_MACBLOCK_LEN)
- lchan->ul_facch_blocks = 6;
-
- /* Confirm data / traffic sending (pass ownership of the msgb/prim) */
- l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
- msgb_free((msg == msg_facch) ? msg_tch : msg_facch);
-
send_burst:
/* Determine which burst should be sent */
burst = BUFPOS(bursts_p, br->bid);
diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c
index 67be75e5..49745570 100644
--- a/src/host/trxcon/src/sched_prim.c
+++ b/src/host/trxcon/src/sched_prim.c
@@ -337,7 +337,8 @@ int l1sched_lchan_emit_data_cnf(struct l1sched_lchan_state *lchan,
{
struct l1sched_prim *prim;
- OSMO_ASSERT(msg != NULL);
+ if (msg == NULL)
+ return -ENODEV;
/* convert from DATA.req to DATA.cnf */
prim = l1sched_prim_from_msgb(msg);