falconia has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-mgw/+/39750?usp=email )
Change subject: E1: change dummy fill frame generation method ......................................................................
E1: change dummy fill frame generation method
In the absence of a proper TFO transform (TS 28.062 section C3.2.1.1), OsmoMGW-E1 inserts constant fill frames when there is no RTP input, or when RTP input fails conversion to TRAU-DL and thus does not enqueue anything to the I.460 mux. (We accept TW-TS-001 and TW-TS-002 from RTP side, but bad frames cannot be converted to TRAU-DL without a TFO transform.)
Prior to the present change, this idle fill of the DL was done using fully hard-coded frames, i.e., the operation of converting the desired fill to TRAU-DL bit format was done once externally and the raw bit frames were hard-coded. Change this approach: use fill frames in RTP format provided by libosmocodec, and execute osmo_rtp2trau() followed by osmo_trau_frame_encode() in the fill frame output path just like we do for regular RTP to DL.
Depends: libosmocore.git I2c510ac62a0786c137115c45eee7a48b9736265f Change-Id: I123f77295c56d61ff9aac5f5d64b25eca01e0d63 --- M TODO-RELEASE M src/libosmo-mgcp/mgcp_e1.c 2 files changed, 35 insertions(+), 157 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/50/39750/1
diff --git a/TODO-RELEASE b/TODO-RELEASE index bdb3915..73a6cd6 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -9,3 +9,4 @@ #library what description / commit summary line libosmocore bump_dep; workaround Bump libosmocore version dependency after I68328adb952ca8833ba047cb3b49ccc6f8a1f1b5 has been merged to libosmocore.git; then remove my_msgb_copy_c wrapper function. +libosmocodec bump_dep We depend on the additions of I2c510ac62a0786c137115c45eee7a48b9736265f diff --git a/src/libosmo-mgcp/mgcp_e1.c b/src/libosmo-mgcp/mgcp_e1.c index f056d75..e3d72e0 100644 --- a/src/libosmo-mgcp/mgcp_e1.c +++ b/src/libosmo-mgcp/mgcp_e1.c @@ -57,149 +57,6 @@ .sign_link = NULL, };
-/* The following EFR TRAU-DL frame is a dummy to be transmitted in the absence - * of RTP-derived TRAU-DL frames. The payload bit content here is the decoder - * homing frame (DHF) of TS 46.060 section 8.2 Table 7 - the best we can do - * in the absence of a proper TFO transform for EFR - while the full TRAU-DL - * frame was generated by passing said EFR DHF through osmo_rtp2trau(). - */ -static const ubit_t idle_tf_efr[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 1, - 1, 1, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, 1, 0, - 1, 0, 0, 0, 1, 1, 1, 1, - 1, 0, 0, 1, 0, 1, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, - 0, 1, 1, 0, 0, 0, 0, 0, - 1, 0, 0, 1, 1, 1, 1, 1, - 0, 0, 0, 1, 1, 1, 0, 1, - 1, 0, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 1, 1, 0, 0, 0, - 1, 0, 0, 0, 1, 1, 1, 1, - 0, 1, 1, 0, 1, 1, 0, 0, - 1, 0, 0, 1, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 1, 0, 1, - 1, 1, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 1, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 0, - 1, 1, 1, 0, 1, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, -}; - -/* The following FRv1 TRAU-DL frame is a dummy to be transmitted in the absence - * of RTP-derived TRAU-DL frames. The payload bit content here is the silence - * frame of TS 46.011 Table 1 - the best we can do without integrating the - * TFO transform for FRv1 from Themyscira libgsmfr2 - while the full TRAU-DL - * frame was generated by passing said FRv1 silence frame through - * osmo_rtp2trau(). - */ -static const ubit_t idle_tf_fr[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, - 1, 0, 1, 0, 1, 0, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 1, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 0, 1, 0, 0, 1, 0, - 1, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 1, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 0, 0, 0, 1, 1, - 1, 1, 0, 0, 0, 1, 0, 0, - 1, 1, 1, 0, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 0, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 1, - 1, 1, 0, 0, 0, 0, 1, 0, - 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 1, 1, 0, - 0, 0, 1, 1, 1, 0, 0, 0, - 1, 1, 0, 0, 1, 1, 1, 0, - 1, 1, 0, 1, 1, 0, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 1, - 1, 1, 0, 1, 1, 0, 0, 0, - 1, 0, 1, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 0, 0, 0, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 1, - 1, 1, 1, 0, 1, 1, 0, 1, - 1, 0, 1, 1, 0, 0, 0, 1, - 1, 0, 0, 1, 1, 1, 0, 1, - 1, 0, 0, 0, 0, 1, 0, 1, - 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 0, 0, - 1, 0, 1, 1, 1, 0, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 0, 1, 1, - 0, 0, 0, 1, 0, 0, 1, 1, - 1, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, -}; - -/* Idle speech frame, see also GSM 08.60, chapter 3.4 */ -static const ubit_t idle_tf_spch[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 1, 1, 1, -}; - /* If the RTP transmission has dropouts for some reason the I.460 TX-Queue may * run empty. In order to make sure that the TRAU frame transmission continues * we generate idle TRAU frames here. */ @@ -208,33 +65,53 @@ struct mgcp_endpoint *endp = user_data; struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.e1_stats; struct msgb *msg = msgb_alloc_c(endp->trunk, E1_TRAU_BITS_MSGB, "E1-I.460-IDLE-TX-TRAU-frame"); - uint8_t *ptr; - const uint8_t *ptr_ft; - enum osmo_trau_frame_type ft; + const uint8_t *dummy_fill_pl; + unsigned dummy_fill_pl_len; + struct osmo_trau_frame tf; + int rc;
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_MUX_EMPTY_CTR));
- /* Choose an appropiate idle frame type */ - ft = endp->e1.trau_rtp_st->type; - switch (ft) { + /* choose dummy fill frame payload based on current codec */ + switch (endp->e1.trau_rtp_st->type) { case OSMO_TRAU16_FT_FR: - ptr_ft = idle_tf_fr; + dummy_fill_pl = osmo_gsm611_silence_frame; + dummy_fill_pl_len = GSM_FR_BYTES; break; case OSMO_TRAU16_FT_EFR: - ptr_ft = idle_tf_efr; + dummy_fill_pl = osmo_gsm660_homing_frame; + dummy_fill_pl_len = GSM_EFR_BYTES; break; default: - /* FIXME: What about 8k subslots and AMR frames? */ - ptr_ft = idle_tf_spch; + LOGPENDP(endp, DE1, LOGL_ERROR, "E1-I.460-IDLE-TX: unsupported frame type\n"); + goto skip; }
- /* Put the replacement into a message buffer and enqueue it into the - * I.460 multiplexer */ - ptr = msgb_put(msg, E1_TRAU_BITS); - memcpy(ptr, ptr_ft, E1_TRAU_BITS); + /* turn it into a TRAU-DL frame */ + memset(&tf, 0, sizeof(tf)); + tf.dir = OSMO_TRAU_DIR_DL; + rc = osmo_rtp2trau(&tf, dummy_fill_pl, dummy_fill_pl_len, endp->e1.trau_rtp_st); + if (rc < 0) { + LOGPENDP(endp, DE1, LOGL_ERROR, + "E1-I.460-IDLE-TX: error converting dummy fill frame!\n"); + goto skip; + } + rc = osmo_trau_frame_encode(msgb_data(msg), msg->data_len, &tf); + if (rc < 0) { + LOGPENDP(endp, DE1, LOGL_ERROR, + "E1-I.460-IDLE-TX: error encoding dummy fill frame!\n"); + goto skip; + } + msgb_put(msg, rc); + + /* enqueue it into the I.460 multiplexer */ LOGPENDP(endp, DE1, LOGL_DEBUG, "E1-I.460-IDLE-TX: enquing %u trau frame bits: %s...\n", msgb_length(msg), osmo_ubit_dump(msgb_data(msg), msgb_length(msg) > DEBUG_BITS_MAX ? DEBUG_BITS_MAX : msgb_length(msg))); osmo_i460_mux_enqueue(endp->e1.schan, msg); + +skip: + rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_TX_FAIL_CTR)); + msgb_free(msg); }
/* called by I.460 de-multiplexer; feed output of I.460 demux into TRAU frame sync */