osmo-bts-trx needlessly applies ECU to its UL output
In a departure from all other OsmoBTS models, osmo-bts-trx seeks to apply a libosmocodec ECU to its UL output, with the ECU inserted into the UL path between GSM 05.03 channel decoding and RTP output via l1sap. More precisely, osmo-bts-trx attempts to apply such ECU to its UL in all speech modes, for both TCH/F and TCH/H, but because libosmocodec currently provides an ECU implementation only for FR1 codec, TCH/FS is the only channel mode that ends up being subjected to UL ECU application by osmo-bts-trx. This misfeature was added to osmo-bts-trx (and no other models) back in early 2018:
The problem, however, is that insertion of an ECU transform into the UL output path of a BTS runs counter to standard GSM architecture. In the standard architecture the BTS is supposed to transmit BFI (bad frame indication) frames in those frame positions where it got bad Rx (or where the frame was stolen for FACCH), and all bad frame handling functions (which include not only the ECU function, but also the comfort noise insertion function) are to be applied by the entity on the receiving end of the frame stream originating from the BTS. This architecture was originally designed with TDM transport in mind, but it carries over to RTP just as well: in RTP a BFI frame is either absence of packet transmission (an intentional gap in the RTP stream) or (with recently added "rtp continuous-streaming" option) a special timing-tick-only RTP packet with zero-length payload. If the entity on the receiving end of the RTP stream is another GSM call leg (TrFO), these BFIs propagate to call leg B DL and are ultimately handled by the spec-compliant Rx DTX handler in the MS; if the entity on the receiving end of the RTP stream is a network edge transcoder or some other process that decodes GSM 06.10 via libgsm, that process is responsible for calling a proper FR1 Rx DTX handler (e.g., Themyscira libgsmfrp) just before the call to gsm_decode(). (For all other GSM codecs the Rx DTX handler has been built into the main body of the standard decoder from the beginning; FR1 is the lone exception.)
It has been claimed that the discrepancy of osmo-bts-trx applying an ECU to its UL output while no other OsmoBTS model does likewise is due to sysmoBTS PHY (a proprietary black box DSP) applying its own version of ECU to its UL output. However, this claim can be easily proven false by observing the output from sysmoBTS PHY under BFI conditions. Testing with both FR1 and EFR codecs on a sysmoBTS (others don't matter for comparison with osmo-bts-trx ECU application, which is effective only for FR1), we can see the following behavior:
- When a traffic frame in the UL is stolen for FACCH (this condition can be easily induced by pressing DTMF keys and thus creating FACCH activity during speech), the PHY only sends GsmL1_Sapi_FacchF (no GsmL1_Sapi_TchF, see the fix in #5974), thus there is no clearly no ECU output being emitted.
- When the MS goes into a DTXu pause (enable 'dtx uplink' in OsmoBSC config and go silent on the test MS) and transmits nothing at all on the air, the PHY emits a GsmL1_Sapi_TchF with zero-length payload in every 20 ms window, indicating that it received nothing on the air. Once again, no ECU output.
- With FR1 codec during DTXu pauses the output from the PHY includes occasional interspersed bogons: most GsmL1_Sapi_TchF indications carry zero-length payloads, indicating BFI, but every now and then there will be a GsmL1_Sapi_TchF carrying an FR1 codec frame presented as valid. However, these occasional frames are garbage, and if they aren't suppressed by the check in l1sap, the result will be highly unpleasant sounds replacing the expected comfort noise. These bogons are likely caused by the weak CRC-3 check in GSM 05.03 channel coding for FR1 (1/8 probability of indicating "good" when decoding radio noise), and they are suppressed by the check in l1sap (common for all BTS models and all speech modes) that suppresses frame output from the PHY and replaces it with BFI if the link quality is too low. In any case, the presence of these bogons in the output from sysmoBTS PHY once again confirms that this DSP is not applying any ECU-style transform to its UL output.
So why did osmo-bts-trx developers back in late 2017 go out of their way to implement an ECU (the original libosmocodec FR ECU was developed specifically for this purpose) and insert it into the UL output path of this BTS model? They clearly noticed poor audio quality with osmo-bts-trx compared to sysmoBTS, but unfortunately they came to wrong conclusions about the cause. In my opinion, the problem they were seeing (or hearing) was actually bug #6033: please look at the cgit link at the beginning of the present write-up, linking to the original commit that added ECU UL application to osmo-bts-trx, and note the "before" part of the diff. Prior to the introduction of ECU, the osmo-bts-trx model-specific code was emitting its BFI as a valid-looking FR1 codec frame with all 260 bits of payload set to 0 - but that BFI marker format was an osmo-bts-trx invention, not any kind of standard! When sent to a standard decoder on the receiving end of the RTP stream, these bogus BFI markers must have produced unpleasant sounds instead of spec-defined bad frame handling:
- If the entity on the receiving end of the RTP stream was another GSM call leg going to a standard (non-Osmocom) GSM MS, the Rx DTX handler in that MS would interpret a frame of all zero bits as a SID (that's how the rules of GSM 06.31 section 6.1.1 will classify such a frame), and would invoke its comfort noise generator. However, because LARc parameters for this CN generation are bogus (a payload of all zero bits constitutes bogus LARc), the resulting "comfort" noise was likely not so comforting.
- If the entity on the receiving end of the RTP stream was GAPK or some other tool that invokes an 06.10 decoder (gsm_decode() from libgsm) without invoking an Rx DTX handler first (against the spec, but the people involved likely thought they could get away with it if they had 'dtx uplink' disabled in OsmoBSC config), the all-zeros FR1 payload was fed directly to the 06.10 decoder, which is still a bogon - and the audio output was once again most likely unpleasant.
Applying an ECU in the UL output path of osmo-bts-trx masked this bug #6033: with the old ECU implemented in 2017-2018, bogus FR1 frames of all zero bits could still be emitted, once Xmaxc was reduced to 0, but if there is only one bad frame here and there, or a short burst of bad frames, short enough for Xmaxc reduction to not reach 0, then the ECU output never exhibits the bogon of #6033.
The correct solution is to first fix bug #6033 (remove the code that emits those bogons, and let l1sap emit the same BFI representation as all other BTS models), and then either remove UL ECU invokation from osmo-bts altogether, or at least make it optional per vty config. And if the latter option is chosen (vty config, rather than removing it altogether), then this ECU provision needs to be moved from osmo-bts-trx into the common part.