5G-LENA nr-v3.0-32-g83aee33
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-bearer-stats-connector.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-connector.h"
9
10#include "nr-bearer-stats-calculator.h"
11
12#include <ns3/config.h>
13#include <ns3/log.h>
14
15namespace ns3
16{
17
18NS_LOG_COMPONENT_DEFINE("NrBearerStatsConnector");
19
23bool
24operator<(const NrBearerStatsConnector::CellIdRnti& a, const NrBearerStatsConnector::CellIdRnti& b)
25{
26 return ((a.cellId < b.cellId) || ((a.cellId == b.cellId) && (a.rnti < b.rnti)));
27}
28
35struct NrBoundCallbackArgument : public SimpleRefCount<NrBoundCallbackArgument>
36{
37 public:
38 Ptr<NrBearerStatsBase> stats;
39 uint64_t imsi;
40 uint16_t cellId;
41};
42
51void
52DlTxPduCallback(Ptr<NrBoundCallbackArgument> arg,
53 std::string path,
54 uint16_t rnti,
55 uint8_t lcid,
56 uint32_t packetSize)
57{
58 NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
59 arg->stats->DlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
60}
61
71void
72DlRxPduCallback(Ptr<NrBoundCallbackArgument> arg,
73 std::string path,
74 uint16_t rnti,
75 uint8_t lcid,
76 uint32_t packetSize,
77 uint64_t delay)
78{
79 NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
80 arg->stats->DlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
81}
82
91void
92UlTxPduCallback(Ptr<NrBoundCallbackArgument> arg,
93 std::string path,
94 uint16_t rnti,
95 uint8_t lcid,
96 uint32_t packetSize)
97{
98 NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
99
100 arg->stats->UlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
101}
102
112void
113UlRxPduCallback(Ptr<NrBoundCallbackArgument> arg,
114 std::string path,
115 uint16_t rnti,
116 uint8_t lcid,
117 uint32_t packetSize,
118 uint64_t delay)
119{
120 NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
121
122 arg->stats->UlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
123}
124
126 : m_connected(false)
127{
128}
129
130void
131NrBearerStatsConnector::EnableRlcStats(Ptr<NrBearerStatsBase> rlcStats)
132{
133 m_rlcStats = rlcStats;
135}
136
137void
138NrBearerStatsConnector::EnablePdcpStats(Ptr<NrBearerStatsBase> pdcpStats)
139{
140 m_pdcpStats = pdcpStats;
142}
143
144void
146{
147 NS_LOG_FUNCTION(this);
148 if (!m_connected)
149 {
150 Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/NewUeContext",
151 MakeBoundCallback(&NrBearerStatsConnector::NotifyNewUeContextEnb, this));
152 Config::Connect(
153 "/NodeList/*/DeviceList/*/LteUeRrc/RandomAccessSuccessful",
155 Config::Connect(
156 "/NodeList/*/DeviceList/*/LteEnbRrc/ConnectionReconfiguration",
158 Config::Connect(
159 "/NodeList/*/DeviceList/*/LteUeRrc/ConnectionReconfiguration",
161 Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart",
162 MakeBoundCallback(&NrBearerStatsConnector::NotifyHandoverStartEnb, this));
163 Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart",
164 MakeBoundCallback(&NrBearerStatsConnector::NotifyHandoverStartUe, this));
165 Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverEndOk",
166 MakeBoundCallback(&NrBearerStatsConnector::NotifyHandoverEndOkEnb, this));
167 Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/HandoverEndOk",
168 MakeBoundCallback(&NrBearerStatsConnector::NotifyHandoverEndOkUe, this));
169 m_connected = true;
170 }
171}
172
173void
175 std::string context,
176 uint64_t imsi,
177 uint16_t cellId,
178 uint16_t rnti)
179{
180 c->ConnectSrb0Traces(context, imsi, cellId, rnti);
181}
182
183void
185 std::string context,
186 uint64_t imsi,
187 uint16_t cellId,
188 uint16_t rnti)
189{
190 c->ConnectSrb1TracesUe(context, imsi, cellId, rnti);
191}
192
193void
195 std::string context,
196 uint64_t imsi,
197 uint16_t cellId,
198 uint16_t rnti)
199{
200 c->ConnectTracesUeIfFirstTime(context, imsi, cellId, rnti);
201}
202
203void
205 std::string context,
206 uint64_t imsi,
207 uint16_t cellId,
208 uint16_t rnti,
209 uint16_t targetCellId)
210{
211 c->DisconnectTracesUe(context, imsi, cellId, rnti);
212}
213
214void
216 std::string context,
217 uint64_t imsi,
218 uint16_t cellId,
219 uint16_t rnti)
220{
221 c->ConnectTracesUe(context, imsi, cellId, rnti);
222}
223
224void
226 std::string context,
227 uint16_t cellId,
228 uint16_t rnti)
229{
230 c->StoreUeManagerPath(context, cellId, rnti);
231}
232
233void
235 std::string context,
236 uint64_t imsi,
237 uint16_t cellId,
238 uint16_t rnti)
239{
240 c->ConnectTracesEnbIfFirstTime(context, imsi, cellId, rnti);
241}
242
243void
245 std::string context,
246 uint64_t imsi,
247 uint16_t cellId,
248 uint16_t rnti,
249 uint16_t targetCellId)
250{
251 c->DisconnectTracesEnb(context, imsi, cellId, rnti);
252}
253
254void
256 std::string context,
257 uint64_t imsi,
258 uint16_t cellId,
259 uint16_t rnti)
260{
261 c->ConnectTracesEnb(context, imsi, cellId, rnti);
262}
263
264void
265NrBearerStatsConnector::StoreUeManagerPath(std::string context, uint16_t cellId, uint16_t rnti)
266{
267 NS_LOG_FUNCTION(this << context << cellId << rnti);
268 std::ostringstream ueManagerPath;
269 ueManagerPath << context.substr(0, context.rfind('/')) << "/UeMap/" << (uint32_t)rnti;
270 CellIdRnti key;
271 key.cellId = cellId;
272 key.rnti = rnti;
273 m_ueManagerPathByCellIdRnti[key] = ueManagerPath.str();
274}
275
276void
277NrBearerStatsConnector::ConnectSrb0Traces(std::string context,
278 uint64_t imsi,
279 uint16_t cellId,
280 uint16_t rnti)
281{
282 NS_LOG_FUNCTION(this << imsi << cellId << rnti);
283 std::string ueRrcPath = context.substr(0, context.rfind('/'));
284 CellIdRnti key;
285 key.cellId = cellId;
286 key.rnti = rnti;
287 std::map<CellIdRnti, std::string>::iterator it = m_ueManagerPathByCellIdRnti.find(key);
288 NS_ASSERT(it != m_ueManagerPathByCellIdRnti.end());
289 std::string ueManagerPath = it->second;
290 NS_LOG_LOGIC(this << " ueManagerPath: " << ueManagerPath);
291 m_ueManagerPathByCellIdRnti.erase(it);
292
293 if (m_rlcStats)
294 {
295 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
296 arg->imsi = imsi;
297 arg->cellId = cellId;
298 arg->stats = m_rlcStats;
299
300 // disconnect eventually previously connected SRB0 both at UE and eNB
301 Config::Disconnect(ueRrcPath + "/Srb0/LteRlc/TxPDU",
302 MakeBoundCallback(&UlTxPduCallback, arg));
303 Config::Disconnect(ueRrcPath + "/Srb0/LteRlc/RxPDU",
304 MakeBoundCallback(&DlRxPduCallback, arg));
305 Config::Disconnect(ueManagerPath + "/Srb0/LteRlc/TxPDU",
306 MakeBoundCallback(&DlTxPduCallback, arg));
307 Config::Disconnect(ueManagerPath + "/Srb0/LteRlc/RxPDU",
308 MakeBoundCallback(&UlRxPduCallback, arg));
309
310 // connect SRB0 both at UE and eNB
311 Config::Connect(ueRrcPath + "/Srb0/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
312 Config::Connect(ueRrcPath + "/Srb0/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
313 Config::Connect(ueManagerPath + "/Srb0/LteRlc/TxPDU",
314 MakeBoundCallback(&DlTxPduCallback, arg));
315 Config::Connect(ueManagerPath + "/Srb0/LteRlc/RxPDU",
316 MakeBoundCallback(&UlRxPduCallback, arg));
317
318 // connect SRB1 at eNB only (at UE SRB1 will be setup later)
319 Config::Connect(ueManagerPath + "/Srb1/LteRlc/TxPDU",
320 MakeBoundCallback(&DlTxPduCallback, arg));
321 Config::Connect(ueManagerPath + "/Srb1/LteRlc/RxPDU",
322 MakeBoundCallback(&UlRxPduCallback, arg));
323 }
324 if (m_pdcpStats)
325 {
326 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
327 arg->imsi = imsi;
328 arg->cellId = cellId;
329 arg->stats = m_pdcpStats;
330
331 // connect SRB1 at eNB only (at UE SRB1 will be setup later)
332 Config::Connect(ueManagerPath + "/Srb1/LtePdcp/RxPDU",
333 MakeBoundCallback(&UlRxPduCallback, arg));
334 Config::Connect(ueManagerPath + "/Srb1/LtePdcp/TxPDU",
335 MakeBoundCallback(&DlTxPduCallback, arg));
336 }
337}
338
339void
340NrBearerStatsConnector::ConnectSrb1TracesUe(std::string ueRrcPath,
341 uint64_t imsi,
342 uint16_t cellId,
343 uint16_t rnti)
344{
345 NS_LOG_FUNCTION(this << imsi << cellId << rnti);
346 if (m_rlcStats)
347 {
348 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
349 arg->imsi = imsi;
350 arg->cellId = cellId;
351 arg->stats = m_rlcStats;
352 Config::Connect(ueRrcPath + "/Srb1/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
353 Config::Connect(ueRrcPath + "/Srb1/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
354 }
355 if (m_pdcpStats)
356 {
357 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
358 arg->imsi = imsi;
359 arg->cellId = cellId;
360 arg->stats = m_pdcpStats;
361 Config::Connect(ueRrcPath + "/Srb1/LtePdcp/RxPDU",
362 MakeBoundCallback(&DlRxPduCallback, arg));
363 Config::Connect(ueRrcPath + "/Srb1/LtePdcp/TxPDU",
364 MakeBoundCallback(&UlTxPduCallback, arg));
365 }
366}
367
368void
369NrBearerStatsConnector::ConnectTracesUeIfFirstTime(std::string context,
370 uint64_t imsi,
371 uint16_t cellId,
372 uint16_t rnti)
373{
374 NS_LOG_FUNCTION(this << context);
375 if (m_imsiSeenUe.find(imsi) == m_imsiSeenUe.end())
376 {
377 m_imsiSeenUe.insert(imsi);
378 ConnectTracesUe(context, imsi, cellId, rnti);
379 }
380}
381
382void
383NrBearerStatsConnector::ConnectTracesEnbIfFirstTime(std::string context,
384 uint64_t imsi,
385 uint16_t cellId,
386 uint16_t rnti)
387{
388 NS_LOG_FUNCTION(this << context);
389 if (m_imsiSeenEnb.find(imsi) == m_imsiSeenEnb.end())
390 {
391 m_imsiSeenEnb.insert(imsi);
392 ConnectTracesEnb(context, imsi, cellId, rnti);
393 }
394}
395
396void
397NrBearerStatsConnector::ConnectTracesUe(std::string context,
398 uint64_t imsi,
399 uint16_t cellId,
400 uint16_t rnti)
401{
402 NS_LOG_FUNCTION(this << context);
403 NS_LOG_LOGIC(this << "expected context should match /NodeList/*/DeviceList/*/LteUeRrc/");
404 std::string basePath = context.substr(0, context.rfind('/'));
405 if (m_rlcStats)
406 {
407 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
408 arg->imsi = imsi;
409 arg->cellId = cellId;
410 arg->stats = m_rlcStats;
411 Config::Connect(basePath + "/DataRadioBearerMap/*/LteRlc/TxPDU",
412 MakeBoundCallback(&UlTxPduCallback, arg));
413 Config::Connect(basePath + "/DataRadioBearerMap/*/LteRlc/RxPDU",
414 MakeBoundCallback(&DlRxPduCallback, arg));
415 Config::Connect(basePath + "/Srb1/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
416 Config::Connect(basePath + "/Srb1/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
417 }
418 if (m_pdcpStats)
419 {
420 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
421 arg->imsi = imsi;
422 arg->cellId = cellId;
423 arg->stats = m_pdcpStats;
424 Config::Connect(basePath + "/DataRadioBearerMap/*/LtePdcp/RxPDU",
425 MakeBoundCallback(&DlRxPduCallback, arg));
426 Config::Connect(basePath + "/DataRadioBearerMap/*/LtePdcp/TxPDU",
427 MakeBoundCallback(&UlTxPduCallback, arg));
428 Config::Connect(basePath + "/Srb1/LtePdcp/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
429 Config::Connect(basePath + "/Srb1/LtePdcp/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
430 }
431}
432
433void
434NrBearerStatsConnector::ConnectTracesEnb(std::string context,
435 uint64_t imsi,
436 uint16_t cellId,
437 uint16_t rnti)
438{
439 NS_LOG_FUNCTION(this << context);
440 NS_LOG_LOGIC(this << "expected context should match /NodeList/*/DeviceList/*/LteEnbRrc/");
441 std::ostringstream basePath;
442 basePath << context.substr(0, context.rfind('/')) << "/UeMap/" << (uint32_t)rnti;
443 if (m_rlcStats)
444 {
445 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
446 arg->imsi = imsi;
447 arg->cellId = cellId;
448 arg->stats = m_rlcStats;
449 Config::Connect(basePath.str() + "/DataRadioBearerMap/*/LteRlc/RxPDU",
450 MakeBoundCallback(&UlRxPduCallback, arg));
451 Config::Connect(basePath.str() + "/DataRadioBearerMap/*/LteRlc/TxPDU",
452 MakeBoundCallback(&DlTxPduCallback, arg));
453 Config::Connect(basePath.str() + "/Srb0/LteRlc/RxPDU",
454 MakeBoundCallback(&UlRxPduCallback, arg));
455 Config::Connect(basePath.str() + "/Srb0/LteRlc/TxPDU",
456 MakeBoundCallback(&DlTxPduCallback, arg));
457 Config::Connect(basePath.str() + "/Srb1/LteRlc/RxPDU",
458 MakeBoundCallback(&UlRxPduCallback, arg));
459 Config::Connect(basePath.str() + "/Srb1/LteRlc/TxPDU",
460 MakeBoundCallback(&DlTxPduCallback, arg));
461 }
462 if (m_pdcpStats)
463 {
464 Ptr<NrBoundCallbackArgument> arg = Create<NrBoundCallbackArgument>();
465 arg->imsi = imsi;
466 arg->cellId = cellId;
467 arg->stats = m_pdcpStats;
468 Config::Connect(basePath.str() + "/DataRadioBearerMap/*/LtePdcp/TxPDU",
469 MakeBoundCallback(&DlTxPduCallback, arg));
470 Config::Connect(basePath.str() + "/DataRadioBearerMap/*/LtePdcp/RxPDU",
471 MakeBoundCallback(&UlRxPduCallback, arg));
472 Config::Connect(basePath.str() + "/Srb1/LtePdcp/TxPDU",
473 MakeBoundCallback(&DlTxPduCallback, arg));
474 Config::Connect(basePath.str() + "/Srb1/LtePdcp/RxPDU",
475 MakeBoundCallback(&UlRxPduCallback, arg));
476 }
477}
478
479void
480NrBearerStatsConnector::DisconnectTracesUe(std::string context,
481 uint64_t imsi,
482 uint16_t cellId,
483 uint16_t rnti)
484{
485 NS_LOG_FUNCTION(this);
486}
487
488void
489NrBearerStatsConnector::DisconnectTracesEnb(std::string context,
490 uint64_t imsi,
491 uint16_t cellId,
492 uint16_t rnti)
493{
494 NS_LOG_FUNCTION(this);
495}
496
497Ptr<NrBearerStatsBase>
499{
500 return m_rlcStats;
501}
502
503Ptr<NrBearerStatsBase>
505{
506 return m_pdcpStats;
507}
508
509} // namespace ns3
static void NotifyHandoverStartEnb(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint16_t targetCellId)
static void NotifyConnectionSetupUe(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
static void NotifyRandomAccessSuccessfulUe(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
static void NotifyConnectionReconfigurationEnb(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
Ptr< NrBearerStatsBase > GetPdcpStats()
static void NotifyHandoverEndOkUe(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
void EnablePdcpStats(Ptr< NrBearerStatsBase > pdcpStats)
static void NotifyHandoverStartUe(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint16_t targetCellId)
void EnableRlcStats(Ptr< NrBearerStatsBase > rlcStats)
Ptr< NrBearerStatsBase > GetRlcStats()
static void NotifyHandoverEndOkEnb(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
static void NotifyConnectionReconfigurationUe(NrBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
static void NotifyNewUeContextEnb(NrBearerStatsConnector *c, std::string context, uint16_t cellid, uint16_t rnti)