A Discrete-Event Network Simulator
API
radio-bearer-stats-connector.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors:
18  * Nicola Baldo <nbaldo@cttc.es>
19  * Manuel Requena <manuel.requena@cttc.es>
20  */
21 
23 
25 
26 #include "ns3/log.h"
27 
28 namespace ns3
29 {
30 
31 NS_LOG_COMPONENT_DEFINE("RadioBearerStatsConnector");
32 
36 bool
39 {
40  return ((a.cellId < b.cellId) || ((a.cellId == b.cellId) && (a.rnti < b.rnti)));
41 }
42 
49 struct BoundCallbackArgument : public SimpleRefCount<BoundCallbackArgument>
50 {
51  public:
53  uint64_t imsi;
54  uint16_t cellId;
55 };
56 
65 void
67  std::string path,
68  uint16_t rnti,
69  uint8_t lcid,
70  uint32_t packetSize)
71 {
72  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
73  arg->stats->DlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
74 }
75 
85 void
87  std::string path,
88  uint16_t rnti,
89  uint8_t lcid,
90  uint32_t packetSize,
91  uint64_t delay)
92 {
93  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
94  arg->stats->DlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
95 }
96 
105 void
107  std::string path,
108  uint16_t rnti,
109  uint8_t lcid,
110  uint32_t packetSize)
111 {
112  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
113  arg->stats->UlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
114 }
115 
125 void
127  std::string path,
128  uint16_t rnti,
129  uint8_t lcid,
130  uint32_t packetSize,
131  uint64_t delay)
132 {
133  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
134  arg->stats->UlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
135 }
136 
138  : m_connected(false)
139 {
140 }
141 
142 void
144 {
145  m_rlcStats = rlcStats;
146  EnsureConnected();
147 }
148 
149 void
151 {
152  m_pdcpStats = pdcpStats;
153  EnsureConnected();
154 }
155 
156 void
158 {
159  NS_LOG_FUNCTION(this);
160  if (!m_connected)
161  {
162  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/NewUeContext",
164 
166  "/NodeList/*/DeviceList/*/LteUeRrc/RandomAccessSuccessful",
168 
169  Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/Srb1Created",
171 
172  Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/DrbCreated",
174 
175  m_connected = true;
176  }
177 }
178 
179 void
180 RadioBearerStatsConnector::StoreUeManagerPath(std::string context, uint16_t cellId, uint16_t rnti)
181 {
182  NS_LOG_FUNCTION(this << context << cellId << rnti);
183  std::string ueManagerPath;
184  ueManagerPath = context.substr(0, context.rfind('/')) + "/UeMap/" + std::to_string(rnti);
185  NS_LOG_DEBUG("ueManagerPath = " << ueManagerPath);
186  CellIdRnti key;
187  key.cellId = cellId;
188  key.rnti = rnti;
189  m_ueManagerPathByCellIdRnti[key] = ueManagerPath;
190 
191  Config::Connect(ueManagerPath + "/DrbCreated",
193 }
194 
195 void
197  std::string context,
198  uint16_t cellId,
199  uint16_t rnti)
200 {
201  NS_LOG_FUNCTION(c << context << cellId << rnti);
202  c->StoreUeManagerPath(context, cellId, rnti);
203 }
204 
205 void
207  std::string context,
208  uint64_t imsi,
209  uint16_t cellId,
210  uint16_t rnti)
211 {
212  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti);
213  c->ConnectTracesSrb0(context, imsi, cellId, rnti);
214 }
215 
216 void
218  std::string context,
219  uint64_t imsi,
220  uint16_t cellId,
221  uint16_t rnti,
222  uint8_t lcid)
223 {
224  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti << (uint16_t)lcid);
225  c->ConnectTracesDrbEnb(context, imsi, cellId, rnti, lcid);
226 }
227 
228 void
230  std::string context,
231  uint64_t imsi,
232  uint16_t cellId,
233  uint16_t rnti)
234 {
235  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti);
236  c->ConnectTracesSrb1(context, imsi, cellId, rnti);
237 }
238 
239 void
241  std::string context,
242  uint64_t imsi,
243  uint16_t cellId,
244  uint16_t rnti,
245  uint8_t lcid)
246 {
247  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti << (uint16_t)lcid);
248  c->ConnectTracesDrbUe(context, imsi, cellId, rnti, lcid);
249 }
250 
251 void
253  uint64_t imsi,
254  uint16_t cellId,
255  uint16_t rnti)
256 {
257  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti);
258  std::string ueRrcPath = context.substr(0, context.rfind('/'));
259  NS_LOG_LOGIC("ueRrcPath = " << ueRrcPath);
260  CellIdRnti key;
261  key.cellId = cellId;
262  key.rnti = rnti;
263  auto it = m_ueManagerPathByCellIdRnti.find(key);
265  std::string ueManagerPath = it->second;
266  NS_LOG_LOGIC("ueManagerPath = " << ueManagerPath);
267  if (m_rlcStats)
268  {
269  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
270  arg->imsi = imsi;
271  arg->cellId = cellId;
272  arg->stats = m_rlcStats;
273  Config::Connect(ueRrcPath + "/Srb0/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
274  Config::Connect(ueRrcPath + "/Srb0/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
275  Config::Connect(ueManagerPath + "/Srb0/LteRlc/TxPDU",
277  Config::Connect(ueManagerPath + "/Srb0/LteRlc/RxPDU",
279  }
280 }
281 
282 void
284  uint64_t imsi,
285  uint16_t cellId,
286  uint16_t rnti)
287 {
288  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti);
289  std::string ueRrcPath = context.substr(0, context.rfind('/'));
290  NS_LOG_LOGIC("ueRrcPath = " << ueRrcPath);
291  CellIdRnti key;
292  key.cellId = cellId;
293  key.rnti = rnti;
294  auto it = m_ueManagerPathByCellIdRnti.find(key);
296  std::string ueManagerPath = it->second;
297  NS_LOG_LOGIC("ueManagerPath = " << ueManagerPath);
298  if (m_rlcStats)
299  {
300  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
301  arg->imsi = imsi;
302  arg->cellId = cellId;
303  arg->stats = m_rlcStats;
304  Config::Connect(ueRrcPath + "/Srb1/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
305  Config::Connect(ueRrcPath + "/Srb1/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
306  Config::Connect(ueManagerPath + "/Srb1/LteRlc/TxPDU",
308  Config::Connect(ueManagerPath + "/Srb1/LteRlc/RxPDU",
310  }
311  if (m_pdcpStats)
312  {
313  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
314  arg->imsi = imsi;
315  arg->cellId = cellId;
316  arg->stats = m_pdcpStats;
317  Config::Connect(ueRrcPath + "/Srb1/LtePdcp/TxPDU",
319  Config::Connect(ueRrcPath + "/Srb1/LtePdcp/RxPDU",
321  Config::Connect(ueManagerPath + "/Srb1/LtePdcp/TxPDU",
323  Config::Connect(ueManagerPath + "/Srb1/LtePdcp/RxPDU",
325  }
326 }
327 
328 void
330  uint64_t imsi,
331  uint16_t cellId,
332  uint16_t rnti,
333  uint8_t lcid)
334 {
335  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti << (uint16_t)lcid);
336  NS_LOG_LOGIC("expected context should match /NodeList/*/DeviceList/*/LteEnbRrc/");
337  std::string basePath;
338  basePath =
339  context.substr(0, context.rfind('/')) + "/DataRadioBearerMap/" + std::to_string(lcid - 2);
340  NS_LOG_LOGIC("basePath = " << basePath);
341  if (m_rlcStats)
342  {
343  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
344  arg->imsi = imsi;
345  arg->cellId = cellId;
346  arg->stats = m_rlcStats;
347  Config::Connect(basePath + "/LteRlc/TxPDU", MakeBoundCallback(&DlTxPduCallback, arg));
348  Config::Connect(basePath + "/LteRlc/RxPDU", MakeBoundCallback(&UlRxPduCallback, arg));
349  }
350  if (m_pdcpStats)
351  {
352  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
353  arg->imsi = imsi;
354  arg->cellId = cellId;
355  arg->stats = m_pdcpStats;
356  bool foundTxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/TxPDU",
358  bool foundRxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/RxPDU",
360  if (!foundTxPdcp && !foundRxPdcp)
361  {
362  NS_LOG_WARN("Unable to connect PDCP traces. This may happen if RlcSm is used");
363  }
364  }
365 }
366 
367 void
369  uint64_t imsi,
370  uint16_t cellId,
371  uint16_t rnti,
372  uint8_t lcid)
373 {
374  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti << (uint16_t)lcid);
375  NS_LOG_LOGIC("expected context should match /NodeList/*/DeviceList/*/LteUeRrc/");
376  std::string basePath;
377  basePath =
378  context.substr(0, context.rfind('/')) + "/DataRadioBearerMap/" + std::to_string(lcid);
379  NS_LOG_LOGIC("basePath = " << basePath);
380  if (m_rlcStats)
381  {
382  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
383  arg->imsi = imsi;
384  arg->cellId = cellId;
385  arg->stats = m_rlcStats;
386  Config::Connect(basePath + "/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
387  Config::Connect(basePath + "/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
388  }
389  if (m_pdcpStats)
390  {
391  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
392  arg->imsi = imsi;
393  arg->cellId = cellId;
394  arg->stats = m_pdcpStats;
395  bool foundTxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/TxPDU",
397  bool foundRxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/RxPDU",
399  if (!foundTxPdcp && !foundRxPdcp)
400  {
401  NS_LOG_WARN("Unable to connect PDCP traces. This may happen if RlcSm is used");
402  }
403  }
404 }
405 
406 void
408  uint64_t imsi,
409  uint16_t cellId,
410  uint16_t rnti)
411 {
412  NS_LOG_FUNCTION(this);
422 }
423 
424 void
426  uint64_t imsi,
427  uint16_t cellId,
428  uint16_t rnti)
429 {
430  NS_LOG_FUNCTION(this);
440 }
441 
442 } // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
This class is very useful when user needs to collect statistics from PDCP and RLC.
void ConnectTracesDrbEnb(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint8_t lcid)
Connects DRB trace sources at eNB to RLC and PDCP calculators.
void ConnectTracesSrb0(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
Connects SRB0 trace sources at UE and eNB to RLC and PDCP calculators.
Ptr< RadioBearerStatsCalculator > m_rlcStats
Calculator for RLC Statistics.
void EnablePdcpStats(Ptr< RadioBearerStatsCalculator > pdcpStats)
Enables trace sinks for PDCP layer.
static void NotifyRandomAccessSuccessfulUe(RadioBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
Function hooked to RandomAccessSuccessful trace source at UE RRC, which is fired upon successful comp...
void ConnectTracesSrb1(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
Connects SRB1 trace sources at UE and eNB to RLC and PDCP calculators.
void StoreUeManagerPath(std::string ueManagerPath, uint16_t cellId, uint16_t rnti)
Creates UE Manager path and stores it in m_ueManagerPathByCellIdRnti.
void EnableRlcStats(Ptr< RadioBearerStatsCalculator > rlcStats)
Enables trace sinks for RLC layer.
static void NotifyNewUeContextEnb(RadioBearerStatsConnector *c, std::string context, uint16_t cellid, uint16_t rnti)
Function hooked to NewUeContext trace source at eNB RRC, which is fired upon creation of a new UE con...
void DisconnectTracesEnb(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
Disconnects all trace sources at eNB to RLC and PDCP calculators.
Ptr< RadioBearerStatsCalculator > m_pdcpStats
Calculator for PDCP Statistics.
std::map< CellIdRnti, std::string > m_ueManagerPathByCellIdRnti
List UE Manager Paths by CellIdRnti.
static void CreatedDrbEnb(RadioBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint8_t lcid)
Function hooked to DrbCreated trace source at UE manager in eNB RRC, which is fired when DRB is creat...
static void CreatedDrbUe(RadioBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint8_t lcid)
Function hooked to DrbCreated trace source at UE RRC, which is fired when DRB is created,...
void DisconnectTracesUe(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
Disconnects all trace sources at UE to RLC and PDCP calculators.
void EnsureConnected()
Connects trace sinks to appropriate trace sources.
void ConnectTracesDrbUe(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint8_t lcid)
Connects DRB trace sources at UE to RLC and PDCP calculators.
bool m_connected
true if traces are connected to sinks, initially set to false
static void CreatedSrb1Ue(RadioBearerStatsConnector *c, std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
Function hooked to Srb1Created trace source at UE RRC, which is fired when SRB1 is created,...
A template-based reference counting class.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
bool ConnectFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:984
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:765
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void UlRxPduCallback(Ptr< BoundCallbackArgument > arg, std::string path, uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
Callback function for UL RX statistics for both RLC and PDCP.
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
void DlTxPduCallback(Ptr< BoundCallbackArgument > arg, std::string path, uint16_t rnti, uint8_t lcid, uint32_t packetSize)
Callback function for DL TX statistics for both RLC and PDCP.
void DlRxPduCallback(Ptr< BoundCallbackArgument > arg, std::string path, uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
Callback function for DL RX statistics for both RLC and PDCP.
void UlTxPduCallback(Ptr< BoundCallbackArgument > arg, std::string path, uint16_t rnti, uint8_t lcid, uint32_t packetSize)
Callback function for UL TX statistics for both RLC and PDCP.
This structure is used as interface between trace sources and RadioBearerStatsCalculator.
Ptr< RadioBearerStatsCalculator > stats
statistics calculator
Struct used as key in m_ueManagerPathByCellIdRnti map.
static const uint32_t packetSize
Packet size generated at the AP.