A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
radio-bearer-stats-connector.cc
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 
22 #include <ns3/log.h>
23 
24 
25 #include "radio-bearer-stats-connector.h"
26 #include "radio-bearer-stats-calculator.h"
27 #include <ns3/lte-enb-rrc.h>
28 #include <ns3/lte-enb-net-device.h>
29 #include <ns3/lte-ue-rrc.h>
30 #include <ns3/lte-ue-net-device.h>
31 
32 NS_LOG_COMPONENT_DEFINE ("RadioBearerStatsConnector");
33 
34 
35 namespace ns3 {
36 
37 
38 
39 bool
40 operator < (const RadioBearerStatsConnector::CellIdRnti& a, const RadioBearerStatsConnector::CellIdRnti& b)
41 {
42  return ( (a.cellId < b.cellId) || ( (a.cellId == b.cellId) && (a.rnti < b.rnti) ) );
43 }
44 
45 struct BoundCallbackArgument : public SimpleRefCount<BoundCallbackArgument>
46 {
47 public:
49  uint64_t imsi;
50  uint16_t cellId;
51 };
52 
53 
54 void
55 DlTxPduCallback (Ptr<BoundCallbackArgument> arg, std::string path,
56  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
57 {
58  NS_LOG_LOGIC (path << rnti << (uint16_t)lcid << packetSize);
59  arg->stats->DlTxPdu (arg->cellId, arg->imsi, rnti, lcid, packetSize);
60 }
61 
62 void
63 DlRxPduCallback (Ptr<BoundCallbackArgument> arg, std::string path,
64  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
65 {
66  NS_LOG_LOGIC (path << rnti << (uint16_t)lcid << packetSize << delay);
67  arg->stats->DlRxPdu (arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
68 }
69 
70 
71 
72 void
73 UlTxPduCallback (Ptr<BoundCallbackArgument> arg, std::string path,
74  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
75 {
76  NS_LOG_LOGIC (path << rnti << (uint16_t)lcid << packetSize);
77 
78  arg->stats->UlTxPdu (arg->cellId, arg->imsi, rnti, lcid, packetSize);
79 }
80 
81 void
82 UlRxPduCallback (Ptr<BoundCallbackArgument> arg, std::string path,
83  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
84 {
85  NS_LOG_LOGIC (path << rnti << (uint16_t)lcid << packetSize << delay);
86 
87  arg->stats->UlRxPdu (arg->cellId, arg->imsi, rnti, lcid, packetSize, delay);
88 }
89 
90 
91 
92 RadioBearerStatsConnector::RadioBearerStatsConnector ()
93  : m_connected (false)
94 {
95 }
96 
97 void
98 RadioBearerStatsConnector::EnableRlcStats (Ptr<RadioBearerStatsCalculator> rlcStats)
99 {
100  m_rlcStats = rlcStats;
101  EnsureConnected ();
102 }
103 
104 void
105 RadioBearerStatsConnector::EnablePdcpStats (Ptr<RadioBearerStatsCalculator> pdcpStats)
106 {
107  m_pdcpStats = pdcpStats;
108  EnsureConnected ();
109 }
110 
111 void
112 RadioBearerStatsConnector::EnsureConnected ()
113 {
114  NS_LOG_FUNCTION (this);
115  if (!m_connected)
116  {
117  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/NewUeContext",
118  MakeBoundCallback (&RadioBearerStatsConnector::NotifyNewUeContextEnb, this));
119  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RandomAccessSuccessful",
120  MakeBoundCallback (&RadioBearerStatsConnector::NotifyRandomAccessSuccessfulUe, this));
121  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/ConnectionReconfiguration",
122  MakeBoundCallback (&RadioBearerStatsConnector::NotifyConnectionReconfigurationEnb, this));
123  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionReconfiguration",
124  MakeBoundCallback (&RadioBearerStatsConnector::NotifyConnectionReconfigurationUe, this));
125  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart",
126  MakeBoundCallback (&RadioBearerStatsConnector::NotifyHandoverStartEnb, this));
127  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart",
128  MakeBoundCallback (&RadioBearerStatsConnector::NotifyHandoverStartUe, this));
129  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverEndOk",
130  MakeBoundCallback (&RadioBearerStatsConnector::NotifyHandoverEndOkEnb, this));
131  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverEndOk",
132  MakeBoundCallback (&RadioBearerStatsConnector::NotifyHandoverEndOkUe, this));
133  m_connected = true;
134  }
135 }
136 
137 void
138 RadioBearerStatsConnector::NotifyRandomAccessSuccessfulUe (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
139 {
140  c->ConnectSrb0Traces (context, imsi, cellId, rnti);
141 }
142 
143 void
144 RadioBearerStatsConnector::NotifyConnectionSetupUe (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
145 {
146  c->ConnectSrb1TracesUe (context, imsi, cellId, rnti);
147 }
148 
149 void
150 RadioBearerStatsConnector::NotifyConnectionReconfigurationUe (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
151 {
152  c->ConnectTracesUeIfFirstTime (context, imsi, cellId, rnti);
153 }
154 
155 void
156 RadioBearerStatsConnector::NotifyHandoverStartUe (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint16_t targetCellId)
157 {
158  c->DisconnectTracesUe (context, imsi, cellId, rnti);
159 }
160 
161 void
162 RadioBearerStatsConnector::NotifyHandoverEndOkUe (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
163 {
164  c->ConnectTracesUe (context, imsi, cellId, rnti);
165 }
166 
167 void
168 RadioBearerStatsConnector::NotifyNewUeContextEnb (RadioBearerStatsConnector* c, std::string context, uint16_t cellId, uint16_t rnti)
169 {
170  c->StoreUeManagerPath (context, cellId, rnti);
171 }
172 
173 void
174 RadioBearerStatsConnector::NotifyConnectionReconfigurationEnb (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
175 {
176  c->ConnectTracesEnbIfFirstTime (context, imsi, cellId, rnti);
177 }
178 
179 void
180 RadioBearerStatsConnector::NotifyHandoverStartEnb (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint16_t targetCellId)
181 {
182  c->DisconnectTracesEnb (context, imsi, cellId, rnti);
183 }
184 
185 void
186 RadioBearerStatsConnector::NotifyHandoverEndOkEnb (RadioBearerStatsConnector* c, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
187 {
188  c->ConnectTracesEnb (context, imsi, cellId, rnti);
189 }
190 
191 void
192 RadioBearerStatsConnector::StoreUeManagerPath (std::string context, uint16_t cellId, uint16_t rnti)
193 {
194  NS_LOG_FUNCTION (this << context << cellId << rnti);
195  std::ostringstream ueManagerPath;
196  ueManagerPath << context.substr (0, context.rfind ("/")) << "/UeMap/" << (uint32_t) rnti;
197  CellIdRnti key;
198  key.cellId = cellId;
199  key.rnti = rnti;
200  m_ueManagerPathByCellIdRnti[key] = ueManagerPath.str ();
201 }
202 
203 void
204 RadioBearerStatsConnector::ConnectSrb0Traces (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
205 {
206  NS_LOG_FUNCTION (this << imsi << cellId << rnti);
207  std::string ueRrcPath = context.substr (0, context.rfind ("/"));
208  CellIdRnti key;
209  key.cellId = cellId;
210  key.rnti = rnti;
211  std::map<CellIdRnti, std::string>::iterator it = m_ueManagerPathByCellIdRnti.find (key);
212  NS_ASSERT (it != m_ueManagerPathByCellIdRnti.end ());
213  std::string ueManagerPath = it->second;
214  NS_LOG_LOGIC (this << " ueManagerPath: " << ueManagerPath);
215  m_ueManagerPathByCellIdRnti.erase (it);
216 
217  if (m_rlcStats)
218  {
219  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
220  arg->imsi = imsi;
221  arg->cellId = cellId;
222  arg->stats = m_rlcStats;
223 
224  // diconnect eventually previously connected SRB0 both at UE and eNB
225  Config::Disconnect (ueRrcPath + "/Srb0/LteRlc/TxPDU",
226  MakeBoundCallback (&UlTxPduCallback, arg));
227  Config::Disconnect (ueRrcPath + "/Srb0/LteRlc/RxPDU",
228  MakeBoundCallback (&DlRxPduCallback, arg));
229  Config::Disconnect (ueManagerPath + "/Srb0/LteRlc/TxPDU",
230  MakeBoundCallback (&DlTxPduCallback, arg));
231  Config::Disconnect (ueManagerPath + "/Srb0/LteRlc/RxPDU",
232  MakeBoundCallback (&UlRxPduCallback, arg));
233 
234  // connect SRB0 both at UE and eNB
235  Config::Connect (ueRrcPath + "/Srb0/LteRlc/TxPDU",
236  MakeBoundCallback (&UlTxPduCallback, arg));
237  Config::Connect (ueRrcPath + "/Srb0/LteRlc/RxPDU",
238  MakeBoundCallback (&DlRxPduCallback, arg));
239  Config::Connect (ueManagerPath + "/Srb0/LteRlc/TxPDU",
240  MakeBoundCallback (&DlTxPduCallback, arg));
241  Config::Connect (ueManagerPath + "/Srb0/LteRlc/RxPDU",
242  MakeBoundCallback (&UlRxPduCallback, arg));
243 
244  // connect SRB1 at eNB only (at UE SRB1 will be setup later)
245  Config::Connect (ueManagerPath + "/Srb1/LteRlc/TxPDU",
246  MakeBoundCallback (&DlTxPduCallback, arg));
247  Config::Connect (ueManagerPath + "/Srb1/LteRlc/RxPDU",
248  MakeBoundCallback (&UlRxPduCallback, arg));
249  }
250  if (m_pdcpStats)
251  {
252  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
253  arg->imsi = imsi;
254  arg->cellId = cellId;
255  arg->stats = m_pdcpStats;
256 
257  // connect SRB1 at eNB only (at UE SRB1 will be setup later)
258  Config::Connect (ueManagerPath + "/Srb1/LtePdcp/RxPDU",
259  MakeBoundCallback (&UlRxPduCallback, arg));
260  Config::Connect (ueManagerPath + "/Srb1/LtePdcp/TxPDU",
261  MakeBoundCallback (&DlTxPduCallback, arg));
262  }
263 }
264 
265 void
266 RadioBearerStatsConnector::ConnectSrb1TracesUe (std::string ueRrcPath, uint64_t imsi, uint16_t cellId, uint16_t rnti)
267 {
268  NS_LOG_FUNCTION (this << imsi << cellId << rnti);
269  if (m_rlcStats)
270  {
271  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
272  arg->imsi = imsi;
273  arg->cellId = cellId;
274  arg->stats = m_rlcStats;
275  Config::Connect (ueRrcPath + "/Srb1/LteRlc/TxPDU",
276  MakeBoundCallback (&UlTxPduCallback, arg));
277  Config::Connect (ueRrcPath + "/Srb1/LteRlc/RxPDU",
278  MakeBoundCallback (&DlRxPduCallback, arg));
279  }
280  if (m_pdcpStats)
281  {
282  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
283  arg->imsi = imsi;
284  arg->cellId = cellId;
285  arg->stats = m_pdcpStats;
286  Config::Connect (ueRrcPath + "/Srb1/LtePdcp/RxPDU",
287  MakeBoundCallback (&DlRxPduCallback, arg));
288  Config::Connect (ueRrcPath + "/Srb1/LtePdcp/TxPDU",
289  MakeBoundCallback (&UlTxPduCallback, arg));
290  }
291 }
292 
293 void
294 RadioBearerStatsConnector::ConnectTracesUeIfFirstTime (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
295 {
296  NS_LOG_FUNCTION (this << context);
297  if (m_imsiSeenUe.find (imsi) == m_imsiSeenUe.end ())
298  {
299  m_imsiSeenUe.insert (imsi);
300  ConnectTracesUe (context, imsi, cellId, rnti);
301  }
302 }
303 
304 void
305 RadioBearerStatsConnector::ConnectTracesEnbIfFirstTime (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
306 {
307  NS_LOG_FUNCTION (this << context);
308  if (m_imsiSeenEnb.find (imsi) == m_imsiSeenEnb.end ())
309  {
310  m_imsiSeenEnb.insert (imsi);
311  ConnectTracesEnb (context, imsi, cellId, rnti);
312  }
313 }
314 
315 void
316 RadioBearerStatsConnector::ConnectTracesUe (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
317 {
318  NS_LOG_FUNCTION (this << context);
319  NS_LOG_LOGIC (this << "expected context should match /NodeList/*/DeviceList/*/LteUeRrc/");
320  std::string basePath = context.substr (0, context.rfind ("/"));
321  if (m_rlcStats)
322  {
323  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
324  arg->imsi = imsi;
325  arg->cellId = cellId;
326  arg->stats = m_rlcStats;
327  Config::Connect (basePath + "/DataRadioBearerMap/*/LteRlc/TxPDU",
328  MakeBoundCallback (&UlTxPduCallback, arg));
329  Config::Connect (basePath + "/DataRadioBearerMap/*/LteRlc/RxPDU",
330  MakeBoundCallback (&DlRxPduCallback, arg));
331  Config::Connect (basePath + "/Srb1/LteRlc/TxPDU",
332  MakeBoundCallback (&UlTxPduCallback, arg));
333  Config::Connect (basePath + "/Srb1/LteRlc/RxPDU",
334  MakeBoundCallback (&DlRxPduCallback, arg));
335 
336  }
337  if (m_pdcpStats)
338  {
339  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
340  arg->imsi = imsi;
341  arg->cellId = cellId;
342  arg->stats = m_pdcpStats;
343  Config::Connect (basePath + "/DataRadioBearerMap/*/LtePdcp/RxPDU",
344  MakeBoundCallback (&DlRxPduCallback, arg));
345  Config::Connect (basePath + "/DataRadioBearerMap/*/LtePdcp/TxPDU",
346  MakeBoundCallback (&UlTxPduCallback, arg));
347  Config::Connect (basePath + "/Srb1/LtePdcp/RxPDU",
348  MakeBoundCallback (&DlRxPduCallback, arg));
349  Config::Connect (basePath + "/Srb1/LtePdcp/TxPDU",
350  MakeBoundCallback (&UlTxPduCallback, arg));
351  }
352 }
353 
354 void
355 RadioBearerStatsConnector::ConnectTracesEnb (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
356 {
357  NS_LOG_FUNCTION (this << context);
358  NS_LOG_LOGIC (this << "expected context should match /NodeList/*/DeviceList/*/LteEnbRrc/");
359  std::ostringstream basePath;
360  basePath << context.substr (0, context.rfind ("/")) << "/UeMap/" << (uint32_t) rnti;
361  if (m_rlcStats)
362  {
363  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
364  arg->imsi = imsi;
365  arg->cellId = cellId;
366  arg->stats = m_rlcStats;
367  Config::Connect (basePath.str () + "/DataRadioBearerMap/*/LteRlc/RxPDU",
368  MakeBoundCallback (&UlRxPduCallback, arg));
369  Config::Connect (basePath.str () + "/DataRadioBearerMap/*/LteRlc/TxPDU",
370  MakeBoundCallback (&DlTxPduCallback, arg));
371  Config::Connect (basePath.str () + "/Srb0/LteRlc/RxPDU",
372  MakeBoundCallback (&UlRxPduCallback, arg));
373  Config::Connect (basePath.str () + "/Srb0/LteRlc/TxPDU",
374  MakeBoundCallback (&DlTxPduCallback, arg));
375  Config::Connect (basePath.str () + "/Srb1/LteRlc/RxPDU",
376  MakeBoundCallback (&UlRxPduCallback, arg));
377  Config::Connect (basePath.str () + "/Srb1/LteRlc/TxPDU",
378  MakeBoundCallback (&DlTxPduCallback, arg));
379  }
380  if (m_pdcpStats)
381  {
382  Ptr<BoundCallbackArgument> arg = Create<BoundCallbackArgument> ();
383  arg->imsi = imsi;
384  arg->cellId = cellId;
385  arg->stats = m_pdcpStats;
386  Config::Connect (basePath.str () + "/DataRadioBearerMap/*/LtePdcp/TxPDU",
387  MakeBoundCallback (&DlTxPduCallback, arg));
388  Config::Connect (basePath.str () + "/DataRadioBearerMap/*/LtePdcp/RxPDU",
389  MakeBoundCallback (&UlRxPduCallback, arg));
390  Config::Connect (basePath.str () + "/Srb1/LtePdcp/TxPDU",
391  MakeBoundCallback (&DlTxPduCallback, arg));
392  Config::Connect (basePath.str () + "/Srb1/LtePdcp/RxPDU",
393  MakeBoundCallback (&UlRxPduCallback, arg));
394  }
395 }
396 
397 void
398 RadioBearerStatsConnector::DisconnectTracesUe (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
399 {
400  NS_LOG_FUNCTION (this);
401 }
402 
403 
404 void
405 RadioBearerStatsConnector::DisconnectTracesEnb (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
406 {
407  NS_LOG_FUNCTION (this);
408 }
409 
410 
411 
412 } // namespace ns3
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void Disconnect(std::string path, const CallbackBase &cb)
Definition: config.cc:734
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:728
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
A template-based reference counting class.