5G-LENA nr-v3.0-32-g83aee33
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-bearer-stats-calculator.cc
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2
3// Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4// Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering, New York University
5//
6// SPDX-License-Identifier: GPL-2.0-only
7
8#include "nr-bearer-stats-calculator.h"
9
10#include "ns3/nstime.h"
11#include "ns3/string.h"
12#include <ns3/log.h>
13
14#include <algorithm>
15#include <vector>
16
17namespace ns3
18{
19
20NS_LOG_COMPONENT_DEFINE("NrBearerStatsCalculator");
21
22NS_OBJECT_ENSURE_REGISTERED(NrBearerStatsCalculator);
23
25 : m_firstWrite(true),
26 m_pendingOutput(false),
27 m_protocolType("RLC")
28{
29 NS_LOG_FUNCTION(this);
30}
31
33 : m_firstWrite(true),
34 m_pendingOutput(false)
35{
36 NS_LOG_FUNCTION(this);
37 m_protocolType = protocolType;
38}
39
41{
42 NS_LOG_FUNCTION(this);
43}
44
45TypeId
47{
48 static TypeId tid =
49 TypeId("ns3::NrBearerStatsCalculator")
50 .SetParent<NrBearerStatsBase>()
51 .AddConstructor<NrBearerStatsCalculator>()
52 .SetGroupName("nr")
53 .AddAttribute("StartTime",
54 "Start time of the on going epoch.",
55 TimeValue(Seconds(0.)),
58 MakeTimeChecker())
59 .AddAttribute("EpochDuration",
60 "Epoch duration.",
61 TimeValue(Seconds(0.25)),
62 MakeTimeAccessor(&NrBearerStatsCalculator::GetEpoch,
64 MakeTimeChecker())
65 .AddAttribute("DlRlcOutputFilename",
66 "Name of the file where the downlink results will be saved.",
67 StringValue("NrDlRlcStatsE2E.txt"),
68 MakeStringAccessor(&NrBearerStatsCalculator::m_dlRlcOutputFilename),
69 MakeStringChecker())
70 .AddAttribute("UlRlcOutputFilename",
71 "Name of the file where the uplink results will be saved.",
72 StringValue("NrUlRlcStatsE2E.txt"),
73 MakeStringAccessor(&NrBearerStatsCalculator::m_ulRlcOutputFilename),
74 MakeStringChecker())
75 .AddAttribute("DlPdcpOutputFilename",
76 "Name of the file where the downlink results will be saved.",
77 StringValue("NrDlPdcpStatsE2E.txt"),
78 MakeStringAccessor(&NrBearerStatsCalculator::m_dlPdcpOutputFilename),
79 MakeStringChecker())
80 .AddAttribute("UlPdcpOutputFilename",
81 "Name of the file where the uplink results will be saved.",
82 StringValue("NrUlPdcpStatsE2E.txt"),
83 MakeStringAccessor(&NrBearerStatsCalculator::m_ulPdcpOutputFilename),
84 MakeStringChecker());
85 return tid;
86}
87
88void
89NrBearerStatsCalculator::DoDispose()
90{
91 NS_LOG_FUNCTION(this);
92 if (m_pendingOutput)
93 {
94 ShowResults();
95 }
96}
97
98void
100{
101 m_startTime = t;
102 // RescheduleEndEpoch ();
103}
104
105Time
107{
108 return m_startTime;
109}
110
111void
113{
114 m_epochDuration = e;
115 // RescheduleEndEpoch ();
116}
117
118Time
120{
121 return m_epochDuration;
122}
123
124void
126 uint64_t imsi,
127 uint16_t rnti,
128 uint8_t lcid,
129 uint32_t packetSize)
130{
131 NS_LOG_FUNCTION(this);
132
133 ImsiLcidPair_t p(imsi, lcid);
134 if (Simulator::Now() >= m_startTime)
135 {
136 m_ulCellId[p] = cellId;
137 m_flowId[p] = LteFlowId_t(rnti, lcid);
138 m_ulTxPackets[p]++;
139 m_ulTxData[p] += packetSize;
140 }
141 m_pendingOutput = true;
142}
143
144void
146 uint64_t imsi,
147 uint16_t rnti,
148 uint8_t lcid,
149 uint32_t packetSize)
150{
151 NS_LOG_FUNCTION(this);
152
153 ImsiLcidPair_t p(imsi, lcid);
154 if (Simulator::Now() >= m_startTime)
155 {
156 m_dlCellId[p] = cellId;
157 m_flowId[p] = LteFlowId_t(rnti, lcid);
158 m_dlTxPackets[p]++;
159 m_dlTxData[p] += packetSize;
160 }
161 m_pendingOutput = true;
162}
163
164void
166 uint64_t imsi,
167 uint16_t rnti,
168 uint8_t lcid,
169 uint32_t packetSize,
170 uint64_t delay)
171{
172 NS_LOG_FUNCTION(this);
173
174 ImsiLcidPair_t p(imsi, lcid);
175 if (Simulator::Now() >= m_startTime)
176 {
177 m_ulCellId[p] = cellId;
178 m_ulRxPackets[p]++;
179 m_ulRxData[p] += packetSize;
180
181 Uint64StatsMap::iterator it = m_ulDelay.find(p);
182 if (it == m_ulDelay.end())
183 {
184 NS_LOG_DEBUG(this << " Creating UL stats calculators for IMSI " << p.m_imsi
185 << " and LCID " << (uint32_t)p.m_lcId);
186 m_ulDelay[p] = CreateObject<MinMaxAvgTotalCalculator<uint64_t>>();
187 m_ulPduSize[p] = CreateObject<MinMaxAvgTotalCalculator<uint32_t>>();
188 }
189 m_ulDelay[p]->Update(delay);
190 m_ulPduSize[p]->Update(packetSize);
191 }
192 m_pendingOutput = true;
193}
194
195void
197 uint64_t imsi,
198 uint16_t rnti,
199 uint8_t lcid,
200 uint32_t packetSize,
201 uint64_t delay)
202{
203 NS_LOG_FUNCTION(this);
204
205 ImsiLcidPair_t p(imsi, lcid);
206 if (Simulator::Now() >= m_startTime)
207 {
208 m_dlCellId[p] = cellId;
209 m_dlRxPackets[p]++;
210 m_dlRxData[p] += packetSize;
211
212 Uint64StatsMap::iterator it = m_dlDelay.find(p);
213 if (it == m_dlDelay.end())
214 {
215 NS_LOG_DEBUG(this << " Creating DL stats calculators for IMSI " << p.m_imsi
216 << " and LCID " << (uint32_t)p.m_lcId);
217 m_dlDelay[p] = CreateObject<MinMaxAvgTotalCalculator<uint64_t>>();
218 m_dlPduSize[p] = CreateObject<MinMaxAvgTotalCalculator<uint32_t>>();
219 }
220 m_dlDelay[p]->Update(delay);
221 m_dlPduSize[p]->Update(packetSize);
222 }
223 m_pendingOutput = true;
224}
225
226void
227NrBearerStatsCalculator::ShowResults()
228{
229 NS_LOG_FUNCTION(this << GetUlOutputFilename().c_str() << GetDlOutputFilename().c_str());
230 NS_LOG_INFO("Write bearer stats to " << GetUlOutputFilename().c_str() << " and in "
231 << GetDlOutputFilename().c_str());
232
233 std::ofstream ulOutFile;
234 std::ofstream dlOutFile;
235
236 if (m_firstWrite)
237 {
238 ulOutFile.open(GetUlOutputFilename().c_str());
239 if (!ulOutFile.is_open())
240 {
241 NS_LOG_ERROR("Can't open file " << GetUlOutputFilename().c_str());
242 return;
243 }
244
245 dlOutFile.open(GetDlOutputFilename().c_str());
246 if (!dlOutFile.is_open())
247 {
248 NS_LOG_ERROR("Can't open file " << GetDlOutputFilename().c_str());
249 return;
250 }
251 m_firstWrite = false;
252 ulOutFile
253 << "% start(s)\tend(s)\tCellId\tIMSI\tRNTI\tLCID\tnTxPDUs\tTxBytes\tnRxPDUs\tRxBytes\t";
254 ulOutFile << "delay(s)\tstdDev(s)\tmin(s)\tmax(s)\t";
255 ulOutFile << "PduSize\tstdDev\tmin\tmax";
256 ulOutFile << std::endl;
257 dlOutFile
258 << "% start(s)\tend(s)\tCellId\tIMSI\tRNTI\tLCID\tnTxPDUs\tTxBytes\tnRxPDUs\tRxBytes\t";
259 dlOutFile << "delay(s)\tstdDev(s)\tmin(s)\tmax(s)\t";
260 dlOutFile << "PduSize\tstdDev\tmin\tmax";
261 dlOutFile << std::endl;
262 }
263 else
264 {
265 ulOutFile.open(GetUlOutputFilename().c_str(), std::ios_base::app);
266 if (!ulOutFile.is_open())
267 {
268 NS_LOG_ERROR("Can't open file " << GetUlOutputFilename().c_str());
269 return;
270 }
271
272 dlOutFile.open(GetDlOutputFilename().c_str(), std::ios_base::app);
273 if (!dlOutFile.is_open())
274 {
275 NS_LOG_ERROR("Can't open file " << GetDlOutputFilename().c_str());
276 return;
277 }
278 }
279
280 WriteUlResults(ulOutFile);
281 WriteDlResults(dlOutFile);
282 m_pendingOutput = false;
283}
284
285void
286NrBearerStatsCalculator::WriteUlResults(std::ofstream& outFile)
287{
288 NS_LOG_FUNCTION(this);
289
290 // Get the unique IMSI / LCID list
291
292 std::vector<ImsiLcidPair_t> pairVector;
293 for (auto& m_ulTxPacket : m_ulTxPackets)
294 {
295 if (find(pairVector.begin(), pairVector.end(), m_ulTxPacket.first) == pairVector.end())
296 {
297 pairVector.push_back(m_ulTxPacket.first);
298 }
299 }
300
301 Time endTime = m_startTime + m_epochDuration;
302 for (auto p : pairVector)
303 {
304 outFile << m_startTime.GetSeconds() << "\t";
305 outFile << endTime.GetSeconds() << "\t";
306 outFile << GetUlCellId(p.m_imsi, p.m_lcId) << "\t";
307 outFile << p.m_imsi << "\t";
308 outFile << m_flowId[p].m_rnti << "\t";
309 outFile << (uint32_t)m_flowId[p].m_lcId << "\t";
310 outFile << GetUlTxPackets(p.m_imsi, p.m_lcId) << "\t";
311 outFile << GetUlTxData(p.m_imsi, p.m_lcId) << "\t";
312 outFile << GetUlRxPackets(p.m_imsi, p.m_lcId) << "\t";
313 outFile << GetUlRxData(p.m_imsi, p.m_lcId) << "\t";
314 std::vector<double> stats = GetUlDelayStats(p.m_imsi, p.m_lcId);
315 for (double& stat : stats)
316 {
317 outFile << stat * 1e-9 << "\t";
318 }
319 stats = GetUlPduSizeStats(p.m_imsi, p.m_lcId);
320 for (double& stat : stats)
321 {
322 outFile << stat << "\t";
323 }
324 outFile << std::endl;
325 }
326
327 outFile.close();
328}
329
330void
331NrBearerStatsCalculator::WriteDlResults(std::ofstream& outFile)
332{
333 NS_LOG_FUNCTION(this);
334
335 // Get the unique IMSI list
336 std::vector<ImsiLcidPair_t> pairVector;
337 for (auto& m_dlTxPacket : m_dlTxPackets)
338 {
339 if (find(pairVector.begin(), pairVector.end(), m_dlTxPacket.first) == pairVector.end())
340 {
341 pairVector.push_back(m_dlTxPacket.first);
342 }
343 }
344
345 Time endTime = m_startTime + m_epochDuration;
346 for (auto p : pairVector)
347 {
348 outFile << m_startTime.GetSeconds() << "\t";
349 outFile << endTime.GetSeconds() << "\t";
350 outFile << GetDlCellId(p.m_imsi, p.m_lcId) << "\t";
351 outFile << p.m_imsi << "\t";
352 outFile << m_flowId[p].m_rnti << "\t";
353 outFile << (uint32_t)m_flowId[p].m_lcId << "\t";
354 outFile << GetDlTxPackets(p.m_imsi, p.m_lcId) << "\t";
355 outFile << GetDlTxData(p.m_imsi, p.m_lcId) << "\t";
356 outFile << GetDlRxPackets(p.m_imsi, p.m_lcId) << "\t";
357 outFile << GetDlRxData(p.m_imsi, p.m_lcId) << "\t";
358 std::vector<double> stats = GetDlDelayStats(p.m_imsi, p.m_lcId);
359 for (double& stat : stats)
360 {
361 outFile << stat * 1e-9 << "\t";
362 }
363 stats = GetDlPduSizeStats(p.m_imsi, p.m_lcId);
364 for (double& stat : stats)
365 {
366 outFile << stat << "\t";
367 }
368 outFile << std::endl;
369 }
370
371 outFile.close();
372}
373
374void
375NrBearerStatsCalculator::ResetResults()
376{
377 NS_LOG_FUNCTION(this);
378
379 m_ulTxPackets.erase(m_ulTxPackets.begin(), m_ulTxPackets.end());
380 m_ulRxPackets.erase(m_ulRxPackets.begin(), m_ulRxPackets.end());
381 m_ulRxData.erase(m_ulRxData.begin(), m_ulRxData.end());
382 m_ulTxData.erase(m_ulTxData.begin(), m_ulTxData.end());
383 m_ulDelay.erase(m_ulDelay.begin(), m_ulDelay.end());
384 m_ulPduSize.erase(m_ulPduSize.begin(), m_ulPduSize.end());
385
386 m_dlTxPackets.erase(m_dlTxPackets.begin(), m_dlTxPackets.end());
387 m_dlRxPackets.erase(m_dlRxPackets.begin(), m_dlRxPackets.end());
388 m_dlRxData.erase(m_dlRxData.begin(), m_dlRxData.end());
389 m_dlTxData.erase(m_dlTxData.begin(), m_dlTxData.end());
390 m_dlDelay.erase(m_dlDelay.begin(), m_dlDelay.end());
391 m_dlPduSize.erase(m_dlPduSize.begin(), m_dlPduSize.end());
392}
393
394void
395NrBearerStatsCalculator::RescheduleEndEpoch()
396{
397 NS_LOG_FUNCTION(this);
398 m_endEpochEvent.Cancel();
399 NS_ASSERT(Simulator::Now().GetMilliSeconds() == 0); // below event time assumes this
400 m_endEpochEvent = Simulator::Schedule(m_startTime + m_epochDuration,
401 &NrBearerStatsCalculator::EndEpoch,
402 this);
403}
404
405void
406NrBearerStatsCalculator::EndEpoch()
407{
408 NS_LOG_FUNCTION(this);
409 ShowResults();
410 ResetResults();
411 m_startTime += m_epochDuration;
412 m_endEpochEvent =
413 Simulator::Schedule(m_epochDuration, &NrBearerStatsCalculator::EndEpoch, this);
414}
415
416uint32_t
417NrBearerStatsCalculator::GetUlTxPackets(uint64_t imsi, uint8_t lcid)
418{
419 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
420 ImsiLcidPair_t p(imsi, lcid);
421 return m_ulTxPackets[p];
422}
423
424uint32_t
425NrBearerStatsCalculator::GetUlRxPackets(uint64_t imsi, uint8_t lcid)
426{
427 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
428 ImsiLcidPair_t p(imsi, lcid);
429 return m_ulRxPackets[p];
430}
431
432uint64_t
433NrBearerStatsCalculator::GetUlTxData(uint64_t imsi, uint8_t lcid)
434{
435 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
436 ImsiLcidPair_t p(imsi, lcid);
437 return m_ulTxData[p];
438}
439
440uint64_t
441NrBearerStatsCalculator::GetUlRxData(uint64_t imsi, uint8_t lcid)
442{
443 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
444 ImsiLcidPair_t p(imsi, lcid);
445 return m_ulRxData[p];
446}
447
448double
449NrBearerStatsCalculator::GetUlDelay(uint64_t imsi, uint8_t lcid)
450{
451 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
452 ImsiLcidPair_t p(imsi, lcid);
453 Uint64StatsMap::iterator it = m_ulDelay.find(p);
454 if (it == m_ulDelay.end())
455 {
456 NS_LOG_ERROR("UL delay for " << imsi << " - " << (uint16_t)lcid << " not found");
457 return 0;
458 }
459 return m_ulDelay[p]->getMean();
460}
461
462std::vector<double>
464{
465 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
466 ImsiLcidPair_t p(imsi, lcid);
467 std::vector<double> stats;
468 Uint64StatsMap::iterator it = m_ulDelay.find(p);
469 if (it == m_ulDelay.end())
470 {
471 stats.push_back(0.0);
472 stats.push_back(0.0);
473 stats.push_back(0.0);
474 stats.push_back(0.0);
475 return stats;
476 }
477 stats.push_back(m_ulDelay[p]->getMean());
478 stats.push_back(m_ulDelay[p]->getStddev());
479 stats.push_back(m_ulDelay[p]->getMin());
480 stats.push_back(m_ulDelay[p]->getMax());
481 return stats;
482}
483
484std::vector<double>
486{
487 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
488 ImsiLcidPair_t p(imsi, lcid);
489 std::vector<double> stats;
490 Uint32StatsMap::iterator it = m_ulPduSize.find(p);
491 if (it == m_ulPduSize.end())
492 {
493 stats.push_back(0.0);
494 stats.push_back(0.0);
495 stats.push_back(0.0);
496 stats.push_back(0.0);
497 return stats;
498 }
499 stats.push_back(m_ulPduSize[p]->getMean());
500 stats.push_back(m_ulPduSize[p]->getStddev());
501 stats.push_back(m_ulPduSize[p]->getMin());
502 stats.push_back(m_ulPduSize[p]->getMax());
503 return stats;
504}
505
506uint32_t
507NrBearerStatsCalculator::GetDlTxPackets(uint64_t imsi, uint8_t lcid)
508{
509 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
510 ImsiLcidPair_t p(imsi, lcid);
511 return m_dlTxPackets[p];
512}
513
514uint32_t
515NrBearerStatsCalculator::GetDlRxPackets(uint64_t imsi, uint8_t lcid)
516{
517 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
518 ImsiLcidPair_t p(imsi, lcid);
519 return m_dlRxPackets[p];
520}
521
522uint64_t
523NrBearerStatsCalculator::GetDlTxData(uint64_t imsi, uint8_t lcid)
524{
525 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
526 ImsiLcidPair_t p(imsi, lcid);
527 return m_dlTxData[p];
528}
529
530uint64_t
531NrBearerStatsCalculator::GetDlRxData(uint64_t imsi, uint8_t lcid)
532{
533 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
534 ImsiLcidPair_t p(imsi, lcid);
535 return m_dlRxData[p];
536}
537
538uint32_t
539NrBearerStatsCalculator::GetUlCellId(uint64_t imsi, uint8_t lcid)
540{
541 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
542 ImsiLcidPair_t p(imsi, lcid);
543 return m_ulCellId[p];
544}
545
546uint32_t
547NrBearerStatsCalculator::GetDlCellId(uint64_t imsi, uint8_t lcid)
548{
549 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
550 ImsiLcidPair_t p(imsi, lcid);
551 return m_dlCellId[p];
552}
553
554double
555NrBearerStatsCalculator::GetDlDelay(uint64_t imsi, uint8_t lcid)
556{
557 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
558 ImsiLcidPair_t p(imsi, lcid);
559 Uint64StatsMap::iterator it = m_dlDelay.find(p);
560 if (it == m_dlDelay.end())
561 {
562 NS_LOG_ERROR("DL delay for " << imsi << " not found");
563 return 0;
564 }
565 return m_dlDelay[p]->getMean();
566}
567
568std::vector<double>
570{
571 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
572 ImsiLcidPair_t p(imsi, lcid);
573 std::vector<double> stats;
574 Uint64StatsMap::iterator it = m_dlDelay.find(p);
575 if (it == m_dlDelay.end())
576 {
577 stats.push_back(0.0);
578 stats.push_back(0.0);
579 stats.push_back(0.0);
580 stats.push_back(0.0);
581 return stats;
582 }
583 stats.push_back(m_dlDelay[p]->getMean());
584 stats.push_back(m_dlDelay[p]->getStddev());
585 stats.push_back(m_dlDelay[p]->getMin());
586 stats.push_back(m_dlDelay[p]->getMax());
587 return stats;
588}
589
590std::vector<double>
592{
593 NS_LOG_FUNCTION(this << imsi << (uint16_t)lcid);
594 ImsiLcidPair_t p(imsi, lcid);
595 std::vector<double> stats;
596 Uint32StatsMap::iterator it = m_dlPduSize.find(p);
597 if (it == m_dlPduSize.end())
598 {
599 stats.push_back(0.0);
600 stats.push_back(0.0);
601 stats.push_back(0.0);
602 stats.push_back(0.0);
603 return stats;
604 }
605 stats.push_back(m_dlPduSize[p]->getMean());
606 stats.push_back(m_dlPduSize[p]->getStddev());
607 stats.push_back(m_dlPduSize[p]->getMin());
608 stats.push_back(m_dlPduSize[p]->getMax());
609 return stats;
610}
611
612std::string
614{
615 if (m_protocolType == "RLC")
616 {
617 return m_ulRlcOutputFilename;
618 }
619 else
620 {
621 return m_ulPdcpOutputFilename;
622 }
623}
624
625std::string
627{
628 if (m_protocolType == "RLC")
629 {
630 return m_dlRlcOutputFilename;
631 }
632 else
633 {
634 return m_dlPdcpOutputFilename;
635 }
636}
637
638} // namespace ns3
std::vector< double > GetUlPduSizeStats(uint64_t imsi, uint8_t lcid)
void UlRxPdu(uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay) override
uint64_t GetDlTxData(uint64_t imsi, uint8_t lcid)
double GetUlDelay(uint64_t imsi, uint8_t lcid)
std::vector< double > GetDlDelayStats(uint64_t imsi, uint8_t lcid)
std::vector< double > GetDlPduSizeStats(uint64_t imsi, uint8_t lcid)
uint64_t GetUlTxData(uint64_t imsi, uint8_t lcid)
uint32_t GetDlCellId(uint64_t imsi, uint8_t lcid)
uint32_t GetDlRxPackets(uint64_t imsi, uint8_t lcid)
void DlTxPdu(uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize) override
void UlTxPdu(uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize) override
uint64_t GetDlRxData(uint64_t imsi, uint8_t lcid)
uint32_t GetUlCellId(uint64_t imsi, uint8_t lcid)
uint32_t GetUlTxPackets(uint64_t imsi, uint8_t lcid)
void DlRxPdu(uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay) override
double GetDlDelay(uint64_t imsi, uint8_t lcid)
uint32_t GetUlRxPackets(uint64_t imsi, uint8_t lcid)
uint64_t GetUlRxData(uint64_t imsi, uint8_t lcid)
std::vector< double > GetUlDelayStats(uint64_t imsi, uint8_t lcid)
uint32_t GetDlTxPackets(uint64_t imsi, uint8_t lcid)