amari.drb: Start of the package
This package will be used to implement E-UTRAN IP Throughput KPI. In hereby patch we add `drb.Sampler` that extracts samples of transmission bursts from `ue_get[stats]` observations. Let's go through what E-UTRAN IP Throughput KPI is and how it motivates functionality provided by this patch. Overview of E-UTRAN IP Throughput computation --------------------------------------------- This KPI is defined in TS 32.450 [1] and aggregates transmission volume and time over bursts of transmissions from an average UE point of view. It should be particularly noted that only the time, during which transmission is going on, should be accounted. For example if an UE receives 10KB over 4ms burst and the rest of the time there is no transmission to it during, say, 1 minute, the downlink IP Throughput for that UE over the minute is 20Mbit/s (= 8·10KB/4ms), not 1.3Kbit/s (= 8·10KB/60s). This KPI basically shows what would be the speed to e.g. download a response for HTTP request issued from a mobile. [1] https://www.etsi.org/deliver/etsi_ts/132400_132499/132450/16.00.00_60/ts_132450v160000p.pdf#page=13 To compute IP Throughput we thus need to know Σ of transmitted amount of bytes, and Σ of the time of all transmission bursts. Σ of the bytes is relatively easy to get. eNB already provides close values in overall `stats` and in per-UE `ue_get[stats]` messages. However there is no anything readily available out-of-the box for Σ of bursts transmission time. Thus we need to measure the time of transmission bursts ourselves somehow. It turns out that with current state of things the only practical way to measure it to some degree is to poll eNB frequently with `ue_get[stats]` and estimate transmission time based on δ of `ue_get` timestamps. Let's see how frequently we need to poll to get to reasonably accuracy of resulting throughput. A common situation for HTTP requests issued via LTE is that response content downloading time takes only few milliseconds. For example I used chromium network profiler to access various sites via internet tethered from my phone and saw that for many requests response content downloading time was e.g. 4ms, 5ms, 3.2ms, etc. The accuracy of measuring transmission time should be thus in the order of millisecond to cover that properly. It makes a real difference for reported throughput, if say a download sample with 10KB took 4ms, or it took e.g. "something under 100ms". In the first case we know that for that sample downlink throughput is 2500KB/s, while in the second case all we know is that downlink throughput is "higher than 100KB/s" - a 25 times difference and not certain. Similarly if we poll at 10ms rate we would get that throughput is "higher than 1000KB/s" - a 2.5 times difference from actual value. The accuracy of 1 millisecond coincides with TTI time and with how downlink/uplink transmissions generally work in LTE. With the above the scheme to compute IP Throughput looks to be as follows: poll eNB at 1000Hz rate for `ue_get[stats]`, process retrieved information into per-UE and per-QCI streams, detect bursts on each UE/QCI pair, and aggregate `tx_bytes` and `tx_time` from every burst. It looks to be straightforward, but 1000Hz polling will likely create non-negligible additional load on the system and disturb eNB itself introducing much jitter and harming its latency requirements. That's probably why eNB actually rate-limits WebSocket requests not to go higher than 100Hz - the frequency 10 times less compared to what we need to get to reasonable accuracy for IP throughput. Fortunately there is additional information that provides a way to improve accuracy of measured `tx_time` even when polled every 10ms at 100Hz rate: that additional information is the number of transmitted transport blocks to/from an UE. If we know that during 10ms frame it was e.g. 4 transport blocks transmitted to the UE, that there were no retransmissions *and* that eNB is not congested, we can reasonably estimate that it was actually a 4ms transmission. And if eNB is congested we can still say that transmission time is somewhere in `[4ms, 10ms]` interval because transmitting each transport block takes 1 TTI. Even if imprecise that still provides some information that could be useful. Also 100Hz polling turns to be acceptable from performance point of view and does not disturb the system much. For example on the callbox machine the process, that issues polls, takes only about 3% of CPU load and only on one core, and the CPU usage of eNB does not practically change and its reported tx/rx latency does not change as well. For sure, there is some disturbance, but it appears to be small. To have a better idea of what rate of polling is possible, I've made an experiment with the poller accessing my own websocket echo server quickly implemented in python. Both the poller and the echo server are not optimized, but without rate-limiting they could go to 8000Hz frequency with reaching 100% CPU usage of one CPU core. That 8000Hz is 80x times more compared to 100Hz frequency actually allowed by eNB. This shows what kind of polling frequency limit the system can handle, if absolutely needed, and that 100Hz turns out to be not so high a frequency. Also the Linux 5.6 kernel, installed on the callbox from Fedora32, is configured with `CONFIG_HZ=1000`, which is likely helping here. Implementation overview ~~~~~~~~~~~~~~~~~~~~~~~ The scheme to compute E-UTRAN IP Throughput is thus as follows: poll eNB at 100Hz frequency for `ue_get[stats]` and retrieve information about per-UE/QCI streams and the number of transport blocks dl/ul-ed to the UE in question during that 10ms frame. Estimate `tx_time` taking into account the number of transmitted transport blocks. And estimate whether eNB is congested or not based on `dl_use_avg`/`ul_use_avg` taken from `stats`. For the latter we also need to poll for `stats` at 100Hz frequency and synchronize `ue_get[stats]` and `stats` requests in time so that they both cover the same time interval of particular frame. Then organize the polling process to provide aggregated statistics in the form of new `x.drb_stats` message, and teach `xamari xlog` to save that messages to `enb.xlog` together with `stats`. Then further adjust `amari.kpi.LogMeasure` and generic `kpi.Measurement` and `kpi.Calc` to handle DRB-related data. ---------------------------------------- In this patch we provide first building block - `Sampler` that extracts bursts of data transmissions from stream of `ue_get[stats]` observations. Even though main idea behind `Sampler` is relatively straightforward, several aspects deserves to be noted: 1. information about transmitted bytes and corresponding transmitted transport blocks is emitted by eNB not synchronized in time. The reason here is that, for example, for DL a block is transmitted via PDCCH+PDSCH during one TTI, and then the base station awaits HARQ ACK/NACK. That ACK/NACK comes later via PUCCH or PUSCH. The time window in between original transmission and reception of the ACK/NACK is 4 TTIs for FDD and 4-13 TTIs for TDD (*). And Amarisoft LTEENB updates counters for dl_total_bytes and dl_tx at different times: ue.erab.dl_total_bytes - right after sending data on PDCCH+PDSCH ue.cell.{dl_tx,dl_retx} - after receiving ACK/NACK via PUCCH|PUSCH this way an update to dl_total_bytes might be seen in one frame (= 10·TTI), while corresponding update to dl_tx/dl_retx might be seen in either same, or next, or next-next frame. We bring `δ(tx_bytes)` and `#tx_tb` in sync ourselves via _BitSync. (*) see e.g. Figure 8.1 in "An introduction to LTE, 2nd ed." 2. when we see multiple transmissions related to UE on different QCIs, we cannot directly use corresponding number of transport blocks to estimate transmissions times because we do not know how eNB scheduler placed those transmissions onto resource map. So without additional information we can only estimate corresponding lower and upper bounds.
Showing
amari/drb.py
0 → 100644
This diff is collapsed.
amari/drb_test.py
0 → 100644
This diff is collapsed.