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