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: Nicola Baldo <nbaldo@cttc.es>
18  * Manuel Requena <manuel.requena@cttc.es>
19  */
20 
22 
24 
25 #include "ns3/log.h"
26 
27 namespace ns3
28 {
29 
30 NS_LOG_COMPONENT_DEFINE("RadioBearerStatsConnector");
31 
35 bool
38 {
39  return ((a.cellId < b.cellId) || ((a.cellId == b.cellId) && (a.rnti < b.rnti)));
40 }
41 
48 struct BoundCallbackArgument : public SimpleRefCount<BoundCallbackArgument>
49 {
50  public:
52  uint64_t imsi;
53  uint16_t cellId;
54 };
55 
64 void
66  std::string path,
67  uint16_t rnti,
68  uint8_t lcid,
69  uint32_t packetSize)
70 {
71  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
72  arg->stats->DlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
73 }
74 
84 void
86  std::string path,
87  uint16_t rnti,
88  uint8_t lcid,
89  uint32_t packetSize,
90  uint64_t delay)
91 {
92  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
93  arg->stats->DlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
94 }
95 
104 void
106  std::string path,
107  uint16_t rnti,
108  uint8_t lcid,
109  uint32_t packetSize)
110 {
111  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize);
112  arg->stats->UlTxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize);
113 }
114 
124 void
126  std::string path,
127  uint16_t rnti,
128  uint8_t lcid,
129  uint32_t packetSize,
130  uint64_t delay)
131 {
132  NS_LOG_FUNCTION(path << rnti << (uint16_t)lcid << packetSize << delay);
133  arg->stats->UlRxPdu(arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
134 }
135 
137  : m_connected(false)
138 {
139 }
140 
141 void
143 {
144  m_rlcStats = rlcStats;
145  EnsureConnected();
146 }
147 
148 void
150 {
151  m_pdcpStats = pdcpStats;
152  EnsureConnected();
153 }
154 
155 void
157 {
158  NS_LOG_FUNCTION(this);
159  if (!m_connected)
160  {
161  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/NewUeContext",
163 
165  "/NodeList/*/DeviceList/*/LteUeRrc/RandomAccessSuccessful",
167 
168  Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/Srb1Created",
170 
171  Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/DrbCreated",
173 
174  m_connected = true;
175  }
176 }
177 
178 void
179 RadioBearerStatsConnector::StoreUeManagerPath(std::string context, uint16_t cellId, uint16_t rnti)
180 {
181  NS_LOG_FUNCTION(this << context << cellId << rnti);
182  std::string ueManagerPath;
183  ueManagerPath = context.substr(0, context.rfind('/')) + "/UeMap/" + std::to_string(rnti);
184  NS_LOG_DEBUG("ueManagerPath = " << ueManagerPath);
185  CellIdRnti key;
186  key.cellId = cellId;
187  key.rnti = rnti;
188  m_ueManagerPathByCellIdRnti[key] = ueManagerPath;
189 
190  Config::Connect(ueManagerPath + "/DrbCreated",
192 }
193 
194 void
196  std::string context,
197  uint16_t cellId,
198  uint16_t rnti)
199 {
200  NS_LOG_FUNCTION(c << context << cellId << rnti);
201  c->StoreUeManagerPath(context, cellId, rnti);
202 }
203 
204 void
206  std::string context,
207  uint64_t imsi,
208  uint16_t cellId,
209  uint16_t rnti)
210 {
211  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti);
212  c->ConnectTracesSrb0(context, imsi, cellId, rnti);
213 }
214 
215 void
217  std::string context,
218  uint64_t imsi,
219  uint16_t cellId,
220  uint16_t rnti,
221  uint8_t lcid)
222 {
223  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti << (uint16_t)lcid);
224  c->ConnectTracesDrbEnb(context, imsi, cellId, rnti, lcid);
225 }
226 
227 void
229  std::string context,
230  uint64_t imsi,
231  uint16_t cellId,
232  uint16_t rnti)
233 {
234  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti);
235  c->ConnectTracesSrb1(context, imsi, cellId, rnti);
236 }
237 
238 void
240  std::string context,
241  uint64_t imsi,
242  uint16_t cellId,
243  uint16_t rnti,
244  uint8_t lcid)
245 {
246  NS_LOG_FUNCTION(c << context << imsi << cellId << rnti << (uint16_t)lcid);
247  c->ConnectTracesDrbUe(context, imsi, cellId, rnti, lcid);
248 }
249 
250 void
252  uint64_t imsi,
253  uint16_t cellId,
254  uint16_t rnti)
255 {
256  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti);
257  std::string ueRrcPath = context.substr(0, context.rfind('/'));
258  NS_LOG_LOGIC("ueRrcPath = " << ueRrcPath);
259  CellIdRnti key;
260  key.cellId = cellId;
261  key.rnti = rnti;
262  std::map<CellIdRnti, std::string>::iterator it = m_ueManagerPathByCellIdRnti.find(key);
264  std::string ueManagerPath = it->second;
265  NS_LOG_LOGIC("ueManagerPath = " << ueManagerPath);
266  if (m_rlcStats)
267  {
268  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
269  arg->imsi = imsi;
270  arg->cellId = cellId;
271  arg->stats = m_rlcStats;
272  Config::Connect(ueRrcPath + "/Srb0/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
273  Config::Connect(ueRrcPath + "/Srb0/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
274  Config::Connect(ueManagerPath + "/Srb0/LteRlc/TxPDU",
276  Config::Connect(ueManagerPath + "/Srb0/LteRlc/RxPDU",
278  }
279 }
280 
281 void
283  uint64_t imsi,
284  uint16_t cellId,
285  uint16_t rnti)
286 {
287  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti);
288  std::string ueRrcPath = context.substr(0, context.rfind('/'));
289  NS_LOG_LOGIC("ueRrcPath = " << ueRrcPath);
290  CellIdRnti key;
291  key.cellId = cellId;
292  key.rnti = rnti;
293  std::map<CellIdRnti, std::string>::iterator it = m_ueManagerPathByCellIdRnti.find(key);
295  std::string ueManagerPath = it->second;
296  NS_LOG_LOGIC("ueManagerPath = " << ueManagerPath);
297  if (m_rlcStats)
298  {
299  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
300  arg->imsi = imsi;
301  arg->cellId = cellId;
302  arg->stats = m_rlcStats;
303  Config::Connect(ueRrcPath + "/Srb1/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
304  Config::Connect(ueRrcPath + "/Srb1/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
305  Config::Connect(ueManagerPath + "/Srb1/LteRlc/TxPDU",
307  Config::Connect(ueManagerPath + "/Srb1/LteRlc/RxPDU",
309  }
310  if (m_pdcpStats)
311  {
312  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
313  arg->imsi = imsi;
314  arg->cellId = cellId;
315  arg->stats = m_pdcpStats;
316  Config::Connect(ueRrcPath + "/Srb1/LtePdcp/TxPDU",
318  Config::Connect(ueRrcPath + "/Srb1/LtePdcp/RxPDU",
320  Config::Connect(ueManagerPath + "/Srb1/LtePdcp/TxPDU",
322  Config::Connect(ueManagerPath + "/Srb1/LtePdcp/RxPDU",
324  }
325 }
326 
327 void
329  uint64_t imsi,
330  uint16_t cellId,
331  uint16_t rnti,
332  uint8_t lcid)
333 {
334  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti << (uint16_t)lcid);
335  NS_LOG_LOGIC("expected context should match /NodeList/*/DeviceList/*/LteEnbRrc/");
336  std::string basePath;
337  basePath =
338  context.substr(0, context.rfind('/')) + "/DataRadioBearerMap/" + std::to_string(lcid - 2);
339  NS_LOG_LOGIC("basePath = " << basePath);
340  if (m_rlcStats)
341  {
342  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
343  arg->imsi = imsi;
344  arg->cellId = cellId;
345  arg->stats = m_rlcStats;
346  Config::Connect(basePath + "/LteRlc/TxPDU", MakeBoundCallback(&DlTxPduCallback, arg));
347  Config::Connect(basePath + "/LteRlc/RxPDU", MakeBoundCallback(&UlRxPduCallback, arg));
348  }
349  if (m_pdcpStats)
350  {
351  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
352  arg->imsi = imsi;
353  arg->cellId = cellId;
354  arg->stats = m_pdcpStats;
355  bool foundTxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/TxPDU",
357  bool foundRxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/RxPDU",
359  if (!foundTxPdcp && !foundRxPdcp)
360  {
361  NS_LOG_WARN("Unable to connect PDCP traces. This may happen if RlcSm is used");
362  }
363  }
364 }
365 
366 void
368  uint64_t imsi,
369  uint16_t cellId,
370  uint16_t rnti,
371  uint8_t lcid)
372 {
373  NS_LOG_FUNCTION(this << context << imsi << cellId << rnti << (uint16_t)lcid);
374  NS_LOG_LOGIC("expected context should match /NodeList/*/DeviceList/*/LteUeRrc/");
375  std::string basePath;
376  basePath =
377  context.substr(0, context.rfind('/')) + "/DataRadioBearerMap/" + std::to_string(lcid);
378  NS_LOG_LOGIC("basePath = " << basePath);
379  if (m_rlcStats)
380  {
381  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
382  arg->imsi = imsi;
383  arg->cellId = cellId;
384  arg->stats = m_rlcStats;
385  Config::Connect(basePath + "/LteRlc/TxPDU", MakeBoundCallback(&UlTxPduCallback, arg));
386  Config::Connect(basePath + "/LteRlc/RxPDU", MakeBoundCallback(&DlRxPduCallback, arg));
387  }
388  if (m_pdcpStats)
389  {
390  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument>();
391  arg->imsi = imsi;
392  arg->cellId = cellId;
393  arg->stats = m_pdcpStats;
394  bool foundTxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/TxPDU",
396  bool foundRxPdcp = Config::ConnectFailSafe(basePath + "/LtePdcp/RxPDU",
398  if (!foundTxPdcp && !foundRxPdcp)
399  {
400  NS_LOG_WARN("Unable to connect PDCP traces. This may happen if RlcSm is used");
401  }
402  }
403 }
404 
405 void
407  uint64_t imsi,
408  uint16_t cellId,
409  uint16_t rnti)
410 {
411  NS_LOG_FUNCTION(this);
421 }
422 
423 void
425  uint64_t imsi,
426  uint16_t cellId,
427  uint16_t rnti)
428 {
429  NS_LOG_FUNCTION(this);
439 }
440 
441 } // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:975
bool ConnectFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:985
#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:768
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.