Commit 2824f50d authored by Kirill Smelkov's avatar Kirill Smelkov

kpi: Calc: Add support for E-UTRAN IP Throughput KPI

This patch provides the final building block for E-UTRAN IP Throughput KPI.
It continues

    d102ffaa (drb: Start of the package)
    5bf7dc1c (amari.{drb,xlog}: Provide aggregated DRB statistics in the form of synthetic x.drb_stats message)
    499a7c1b (amari.kpi: Teach LogMeasure to handle x.drb_stats messages)

Quoting those patches

    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.						<-- NOTE

So here we implement that last noted step:

We add Calc.eutran_ip_throughput() whose implementation is relatively
straightforward as the hard part is done by amari.drb and amari.kpi - in the
Calc we basically need to only divide provided DRB.IPVolDl / DRB.IPTimeDl.
parent 499a7c1b
......@@ -27,8 +27,8 @@
information is emitted in the form of synthetic x.drb_stats message whose
generation is integrated into amari.xlog package.
Please see amari.kpi package that turns x.drb_stats data into
measurements related to E-UTRAN IP Throughput KPI.
Please see amari.kpi and xlte.kpi packages that turn x.drb_stats data into
final E-UTRAN IP Throughput KPI value.
See also the following related 3GPP standards references:
......
......@@ -21,7 +21,7 @@
- Calc is KPI calculator. It can be instantiated on MeasurementLog and time
interval over which to perform computations. Use Calc methods such as
.erab_accessibility() to compute KPIs.
.erab_accessibility() and .eutran_ip_throughput() to compute KPIs.
- MeasurementLog maintains journal with result of measurements. Use .append()
to populate it with data.
......@@ -58,6 +58,7 @@ from golang import func
# following methods for computing 3GPP KPIs:
#
# .erab_accessibility() - TS 32.450 6.1.1 "E-RAB Accessibility"
# .eutran_ip_throughput() - TS 32.450 6.3.1 "E-UTRAN IP Throughput"
# TODO other KPIs
#
# Upon construction specified time interval is potentially widened to cover
......@@ -589,6 +590,71 @@ def _success_rate(calc, fini, init): # -> Interval in [0,1]
return Interval(a,b)
# eutran_ip_throughput computes "E-UTRAN IP Throughput" KPI.
#
# It returns the following:
#
# - IPThp[QCI][dl,ul] IP throughput per QCI for downlink and uplink (bit/s)
#
# All elements are returned as Intervals with information about confidence for
# computed values.
#
# NOTE: the unit of the result is bit/s, not kbit/s.
#
# 3GPP reference: TS 32.450 6.3.1 "E-UTRAN IP Throughput".
@func(Calc)
def eutran_ip_throughput(calc): # -> IPThp[QCI][dl,ul]
qdlΣv = np.zeros(nqci, dtype=np.float64)
qdlΣt = np.zeros(nqci, dtype=np.float64)
qdlΣte = np.zeros(nqci, dtype=np.float64)
qulΣv = np.zeros(nqci, dtype=np.float64)
qulΣt = np.zeros(nqci, dtype=np.float64)
qulΣte = np.zeros(nqci, dtype=np.float64)
for m in calc._miter():
τ = m['X.δT']
for qci in range(nqci):
dl_vol = m["DRB.IPVolDl.QCI"] [qci]
dl_time = m["DRB.IPTimeDl.QCI"] [qci]
dl_time_err = m["XXX.DRB.IPTimeDl_err.QCI"] [qci]
ul_vol = m["DRB.IPVolUl.QCI"] [qci]
ul_time = m["DRB.IPTimeUl.QCI"] [qci]
ul_time_err = m["XXX.DRB.IPTimeUl_err.QCI"] [qci]
if isNA(dl_vol) or isNA(dl_time) or isNA(dl_time_err):
# don't account uncertainty - here it is harder to do compared
# to erab_accessibility and the benefit is not clear. Follow
# plain 3GPP spec for now.
pass
else:
qdlΣv[qci] += dl_vol
qdlΣt[qci] += dl_time
qdlΣte[qci] += dl_time_err
if isNA(ul_vol) or isNA(ul_time) or isNA(ul_time_err):
# no uncertainty accounting - see ^^^
pass
else:
qulΣv[qci] += ul_vol
qulΣt[qci] += ul_time
qulΣte[qci] += ul_time_err
thp = np.zeros(nqci, dtype=np.dtype([
('dl', Interval._dtype),
('ul', Interval._dtype),
]))
for qci in range(nqci):
if qdlΣt[qci] > 0:
thp[qci]['dl']['lo'] = qdlΣv[qci] / (qdlΣt[qci] + qdlΣte[qci])
thp[qci]['dl']['hi'] = qdlΣv[qci] / (qdlΣt[qci] - qdlΣte[qci])
if qulΣt[qci] > 0:
thp[qci]['ul']['lo'] = qulΣv[qci] / (qulΣt[qci] + qulΣte[qci])
thp[qci]['ul']['hi'] = qulΣv[qci] / (qulΣt[qci] - qulΣte[qci])
return thp
# _miter iterates through [.τ_lo, .τ_hi) yielding Measurements.
#
# The measurements are yielded with consecutive timestamps. There is no gaps
......
......@@ -439,6 +439,61 @@ def test_Calc_erab_accessibility():
_(InititialEPSBEstabSR, 100 * 2*3*4 / (7*8*9))
# verify Calc.eutran_ip_throughput .
def test_Calc_eutran_ip_throughput():
# most of the job is done by drivers collecting DRB.IPVol{Dl,Ul} and DRB.IPTime{Dl,Ul}
# here we verify final aggregation, that eutran_ip_throughput does, only lightly.
m = Measurement()
m['X.Tstart'] = 10
m['X.δT'] = 10
m['DRB.IPVolDl.5'] = 55e6
m['DRB.IPVolUl.5'] = 55e5
m['DRB.IPTimeDl.5'] = 1e2
m['DRB.IPTimeUl.5'] = 1e2
m['DRB.IPVolDl.7'] = 75e6
m['DRB.IPVolUl.7'] = 75e5
m['DRB.IPTimeDl.7'] = 1e2
m['DRB.IPTimeUl.7'] = 1e2
m['DRB.IPVolDl.9'] = 0
m['DRB.IPVolUl.9'] = 0
m['DRB.IPTimeDl.9'] = 0
m['DRB.IPTimeUl.9'] = 0
for qci in {5,7,9}:
m['XXX.DRB.IPTimeDl_err.QCI'][qci] = 0
m['XXX.DRB.IPTimeUl_err.QCI'][qci] = 0
# (other QCIs are left with na)
for qci in set(range(nqci)).difference({5,7,9}):
assert isNA(m['DRB.IPVolDl.QCI'][qci])
assert isNA(m['DRB.IPVolUl.QCI'][qci])
assert isNA(m['DRB.IPTimeDl.QCI'][qci])
assert isNA(m['DRB.IPTimeUl.QCI'][qci])
assert isNA(m['XXX.DRB.IPTimeDl_err.QCI'][qci])
assert isNA(m['XXX.DRB.IPTimeUl_err.QCI'][qci])
mlog = MeasurementLog()
mlog.append(m)
calc = Calc(mlog, 10,20)
thp = calc.eutran_ip_throughput()
def I(x): return Interval(x,x)
assert thp[5]['dl'] == I(55e4)
assert thp[5]['ul'] == I(55e3)
assert thp[7]['dl'] == I(75e4)
assert thp[7]['ul'] == I(75e3)
assert thp[9]['dl'] == I(0)
assert thp[9]['ul'] == I(0)
for qci in set(range(nqci)).difference({5,7,9}):
assert thp[qci]['dl'] == I(0)
assert thp[qci]['ul'] == I(0)
# verify Σqci.
def test_Σqci():
m = Measurement()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment