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 #include <ns3/fatal-error.h>
22 #include <ns3/log.h>
23 #include <ns3/nstime.h>
24 #include <ns3/node-list.h>
25 #include <ns3/node.h>
26 #include <ns3/simulator.h>
27 
28 #include "lte-rrc-protocol-ideal.h"
29 #include "lte-ue-rrc.h"
30 #include "lte-enb-rrc.h"
31 #include "lte-enb-net-device.h"
32 #include "lte-ue-net-device.h"
33 
34 namespace ns3 {
35 
36 NS_LOG_COMPONENT_DEFINE ("LteRrcProtocolIdeal");
37 
38 /**
39  * \ingroup lte
40  *
41  */
42 
43 /// RRC ideal message delay
44 static const Time RRC_IDEAL_MSG_DELAY = MilliSeconds (0);
45 
46 NS_OBJECT_ENSURE_REGISTERED (LteUeRrcProtocolIdeal);
47 
LteUeRrcProtocolIdeal()48 LteUeRrcProtocolIdeal::LteUeRrcProtocolIdeal ()
49   :  m_ueRrcSapProvider (0),
50      m_enbRrcSapProvider (0)
51 {
52   m_ueRrcSapUser = new MemberLteUeRrcSapUser<LteUeRrcProtocolIdeal> (this);
53 }
54 
~LteUeRrcProtocolIdeal()55 LteUeRrcProtocolIdeal::~LteUeRrcProtocolIdeal ()
56 {
57 }
58 
59 void
DoDispose()60 LteUeRrcProtocolIdeal::DoDispose ()
61 {
62   NS_LOG_FUNCTION (this);
63   delete m_ueRrcSapUser;
64   m_rrc = 0;
65 }
66 
67 TypeId
GetTypeId(void)68 LteUeRrcProtocolIdeal::GetTypeId (void)
69 {
70   static TypeId tid = TypeId ("ns3::LteUeRrcProtocolIdeal")
71     .SetParent<Object> ()
72     .SetGroupName("Lte")
73     .AddConstructor<LteUeRrcProtocolIdeal> ()
74     ;
75   return tid;
76 }
77 
78 void
SetLteUeRrcSapProvider(LteUeRrcSapProvider * p)79 LteUeRrcProtocolIdeal::SetLteUeRrcSapProvider (LteUeRrcSapProvider* p)
80 {
81   m_ueRrcSapProvider = p;
82 }
83 
84 LteUeRrcSapUser*
GetLteUeRrcSapUser()85 LteUeRrcProtocolIdeal::GetLteUeRrcSapUser ()
86 {
87   return m_ueRrcSapUser;
88 }
89 
90 void
SetUeRrc(Ptr<LteUeRrc> rrc)91 LteUeRrcProtocolIdeal::SetUeRrc (Ptr<LteUeRrc> rrc)
92 {
93   m_rrc = rrc;
94 }
95 
96 void
DoSetup(LteUeRrcSapUser::SetupParameters params)97 LteUeRrcProtocolIdeal::DoSetup (LteUeRrcSapUser::SetupParameters params)
98 {
99   NS_LOG_FUNCTION (this);
100   // We don't care about SRB0/SRB1 since we use ideal RRC messages.
101 }
102 
103 void
DoSendRrcConnectionRequest(LteRrcSap::RrcConnectionRequest msg)104 LteUeRrcProtocolIdeal::DoSendRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg)
105 {
106   // initialize the RNTI and get the EnbLteRrcSapProvider for the
107   // eNB we are currently attached to
108   m_rnti = m_rrc->GetRnti ();
109   SetEnbRrcSapProvider ();
110 
111   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
112                        &LteEnbRrcSapProvider::RecvRrcConnectionRequest,
113                        m_enbRrcSapProvider,
114                        m_rnti,
115                        msg);
116 }
117 
118 void
DoSendRrcConnectionSetupCompleted(LteRrcSap::RrcConnectionSetupCompleted msg)119 LteUeRrcProtocolIdeal::DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
120 {
121   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
122 		       &LteEnbRrcSapProvider::RecvRrcConnectionSetupCompleted,
123                        m_enbRrcSapProvider,
124 		       m_rnti,
125 		       msg);
126 }
127 
128 void
DoSendRrcConnectionReconfigurationCompleted(LteRrcSap::RrcConnectionReconfigurationCompleted msg)129 LteUeRrcProtocolIdeal::DoSendRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg)
130 {
131   // re-initialize the RNTI and get the EnbLteRrcSapProvider for the
132   // eNB we are currently attached to
133   m_rnti = m_rrc->GetRnti ();
134   SetEnbRrcSapProvider ();
135 
136    Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
137                         &LteEnbRrcSapProvider::RecvRrcConnectionReconfigurationCompleted,
138                         m_enbRrcSapProvider,
139                         m_rnti,
140                         msg);
141 }
142 
143 void
DoSendRrcConnectionReestablishmentRequest(LteRrcSap::RrcConnectionReestablishmentRequest msg)144 LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
145 {
146    Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
147 		       &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentRequest,
148                        m_enbRrcSapProvider,
149 		       m_rnti,
150                         msg);
151 }
152 
153 void
DoSendRrcConnectionReestablishmentComplete(LteRrcSap::RrcConnectionReestablishmentComplete msg)154 LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
155 {
156    Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
157 		       &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentComplete,
158                        m_enbRrcSapProvider,
159 		       m_rnti,
160 msg);
161 }
162 
163 void
DoSendMeasurementReport(LteRrcSap::MeasurementReport msg)164 LteUeRrcProtocolIdeal::DoSendMeasurementReport (LteRrcSap::MeasurementReport msg)
165 {
166    Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
167                         &LteEnbRrcSapProvider::RecvMeasurementReport,
168                         m_enbRrcSapProvider,
169                         m_rnti,
170                         msg);
171 }
172 
173 void
DoSendIdealUeContextRemoveRequest(uint16_t rnti)174 LteUeRrcProtocolIdeal::DoSendIdealUeContextRemoveRequest (uint16_t rnti)
175 {
176   NS_LOG_FUNCTION (this);
177 
178    uint16_t cellId = m_rrc->GetCellId ();
179    // re-initialize the RNTI and get the EnbLteRrcSapProvider for the
180    // eNB we are currently attached to or attempting random access to
181    // a target eNB
182    m_rnti = m_rrc->GetRnti ();
183 
184    NS_LOG_DEBUG ("RNTI " << rnti
185                  << " sending UE context remove request to cell id " << cellId);
186    NS_ABORT_MSG_IF (m_rnti != rnti, "RNTI mismatch");
187 
188    SetEnbRrcSapProvider (); //the provider has to be reset since the cell might have changed due to handover
189    //ideally informing eNB
190    Simulator::Schedule (RRC_IDEAL_MSG_DELAY, &LteEnbRrcSapProvider::RecvIdealUeContextRemoveRequest,
191                         m_enbRrcSapProvider, m_rnti);
192 }
193 
194 void
SetEnbRrcSapProvider()195 LteUeRrcProtocolIdeal::SetEnbRrcSapProvider ()
196 {
197   NS_LOG_FUNCTION (this);
198 
199   uint16_t cellId = m_rrc->GetCellId ();
200   NS_LOG_DEBUG ("RNTI " << m_rnti << " connected to cell " << cellId);
201 
202   // walk list of all nodes to get the peer eNB
203   Ptr<LteEnbNetDevice> enbDev;
204   NodeList::Iterator listEnd = NodeList::End ();
205   bool found = false;
206   for (NodeList::Iterator i = NodeList::Begin ();
207        (i != listEnd) && (!found);
208        ++i)
209     {
210       Ptr<Node> node = *i;
211       int nDevs = node->GetNDevices ();
212       for (int j = 0;
213            (j < nDevs) && (!found);
214            j++)
215         {
216           enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
217           if (enbDev == 0)
218             {
219               continue;
220             }
221           else
222             {
223               if (enbDev->HasCellId (cellId))
224                 {
225                   found = true;
226                   break;
227                 }
228             }
229         }
230     }
231   NS_ASSERT_MSG (found, " Unable to find eNB with CellId =" << cellId);
232   m_enbRrcSapProvider = enbDev->GetRrc ()->GetLteEnbRrcSapProvider ();
233   Ptr<LteEnbRrcProtocolIdeal> enbRrcProtocolIdeal = enbDev->GetRrc ()->GetObject<LteEnbRrcProtocolIdeal> ();
234   enbRrcProtocolIdeal->SetUeRrcSapProvider (m_rnti, m_ueRrcSapProvider);
235 }
236 
237 
238 NS_OBJECT_ENSURE_REGISTERED (LteEnbRrcProtocolIdeal);
239 
LteEnbRrcProtocolIdeal()240 LteEnbRrcProtocolIdeal::LteEnbRrcProtocolIdeal ()
241   :  m_enbRrcSapProvider (0)
242 {
243   NS_LOG_FUNCTION (this);
244   m_enbRrcSapUser = new MemberLteEnbRrcSapUser<LteEnbRrcProtocolIdeal> (this);
245 }
246 
~LteEnbRrcProtocolIdeal()247 LteEnbRrcProtocolIdeal::~LteEnbRrcProtocolIdeal ()
248 {
249   NS_LOG_FUNCTION (this);
250 }
251 
252 void
DoDispose()253 LteEnbRrcProtocolIdeal::DoDispose ()
254 {
255   NS_LOG_FUNCTION (this);
256   delete m_enbRrcSapUser;
257 }
258 
259 TypeId
GetTypeId(void)260 LteEnbRrcProtocolIdeal::GetTypeId (void)
261 {
262   static TypeId tid = TypeId ("ns3::LteEnbRrcProtocolIdeal")
263     .SetParent<Object> ()
264     .SetGroupName("Lte")
265     .AddConstructor<LteEnbRrcProtocolIdeal> ()
266     ;
267   return tid;
268 }
269 
270 void
SetLteEnbRrcSapProvider(LteEnbRrcSapProvider * p)271 LteEnbRrcProtocolIdeal::SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p)
272 {
273   m_enbRrcSapProvider = p;
274 }
275 
276 LteEnbRrcSapUser*
GetLteEnbRrcSapUser()277 LteEnbRrcProtocolIdeal::GetLteEnbRrcSapUser ()
278 {
279   return m_enbRrcSapUser;
280 }
281 
282 void
SetCellId(uint16_t cellId)283 LteEnbRrcProtocolIdeal::SetCellId (uint16_t cellId)
284 {
285   m_cellId = cellId;
286 }
287 
288 LteUeRrcSapProvider*
GetUeRrcSapProvider(uint16_t rnti)289 LteEnbRrcProtocolIdeal::GetUeRrcSapProvider (uint16_t rnti)
290 {
291   std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it;
292   it = m_enbRrcSapProviderMap.find (rnti);
293   NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti);
294   return it->second;
295 }
296 
297 void
SetUeRrcSapProvider(uint16_t rnti,LteUeRrcSapProvider * p)298 LteEnbRrcProtocolIdeal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p)
299 {
300   std::map<uint16_t, LteUeRrcSapProvider*>::iterator it;
301   it = m_enbRrcSapProviderMap.find (rnti);
302   NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "Cell id " << m_cellId
303                                          << " could not find RNTI = " << rnti);
304   it->second = p;
305 }
306 
307 void
DoSetupUe(uint16_t rnti,LteEnbRrcSapUser::SetupUeParameters params)308 LteEnbRrcProtocolIdeal::DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params)
309 {
310   NS_LOG_FUNCTION (this << rnti);
311 
312   // // walk list of all nodes to get the peer UE RRC SAP Provider
313   // Ptr<LteUeRrc> ueRrc;
314   // NodeList::Iterator listEnd = NodeList::End ();
315   // bool found = false;
316   // for (NodeList::Iterator i = NodeList::Begin (); (i != listEnd) && (found == false); i++)
317   //   {
318   //     Ptr<Node> node = *i;
319   //     int nDevs = node->GetNDevices ();
320   //     for (int j = 0; j < nDevs; j++)
321   //       {
322   //         Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
323   //         if (!ueDev)
324   //           {
325   //             continue;
326   //           }
327   //         else
328   //           {
329   //             ueRrc = ueDev->GetRrc ();
330   //             if ((ueRrc->GetRnti () == rnti) && (ueRrc->GetCellId () == m_cellId))
331   //               {
332   //       	  found = true;
333   //       	  break;
334   //               }
335   //           }
336   //       }
337   //   }
338   // NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
339   // m_enbRrcSapProviderMap[rnti] = ueRrc->GetLteUeRrcSapProvider ();
340 
341 
342   // just create empty entry, the UeRrcSapProvider will be set by the
343   // ue upon connection request or connection reconfiguration
344   // completed
345   m_enbRrcSapProviderMap[rnti] = 0;
346 
347 }
348 
349 void
DoRemoveUe(uint16_t rnti)350 LteEnbRrcProtocolIdeal::DoRemoveUe (uint16_t rnti)
351 {
352   NS_LOG_FUNCTION (this << rnti);
353   m_enbRrcSapProviderMap.erase (rnti);
354 }
355 
356 void
DoSendSystemInformation(uint16_t cellId,LteRrcSap::SystemInformation msg)357 LteEnbRrcProtocolIdeal::DoSendSystemInformation (uint16_t cellId, LteRrcSap::SystemInformation msg)
358 {
359   NS_LOG_FUNCTION (this << cellId);
360   // walk list of all nodes to get UEs with this cellId
361   Ptr<LteUeRrc> ueRrc;
362   for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
363     {
364       Ptr<Node> node = *i;
365       int nDevs = node->GetNDevices ();
366       for (int j = 0; j < nDevs; ++j)
367         {
368           Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
369           if (ueDev != 0)
370             {
371               Ptr<LteUeRrc> ueRrc = ueDev->GetRrc ();
372               NS_LOG_LOGIC ("considering UE IMSI " << ueDev->GetImsi () << " that has cellId " << ueRrc->GetCellId ());
373               if (ueRrc->GetCellId () == cellId)
374                 {
375                   NS_LOG_LOGIC ("sending SI to IMSI " << ueDev->GetImsi ());
376                   ueRrc->GetLteUeRrcSapProvider ()->RecvSystemInformation (msg);
377                   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
378                                        &LteUeRrcSapProvider::RecvSystemInformation,
379                                        ueRrc->GetLteUeRrcSapProvider (),
380                                        msg);
381                 }
382             }
383         }
384     }
385 }
386 
387 void
DoSendRrcConnectionSetup(uint16_t rnti,LteRrcSap::RrcConnectionSetup msg)388 LteEnbRrcProtocolIdeal::DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg)
389 {
390   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
391 		       &LteUeRrcSapProvider::RecvRrcConnectionSetup,
392 		       GetUeRrcSapProvider (rnti),
393 		       msg);
394 }
395 
396 void
DoSendRrcConnectionReconfiguration(uint16_t rnti,LteRrcSap::RrcConnectionReconfiguration msg)397 LteEnbRrcProtocolIdeal::DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg)
398 {
399   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
400 		       &LteUeRrcSapProvider::RecvRrcConnectionReconfiguration,
401 		       GetUeRrcSapProvider (rnti),
402 		       msg);
403 }
404 
405 void
DoSendRrcConnectionReestablishment(uint16_t rnti,LteRrcSap::RrcConnectionReestablishment msg)406 LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg)
407 {
408   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
409 		       &LteUeRrcSapProvider::RecvRrcConnectionReestablishment,
410 		       GetUeRrcSapProvider (rnti),
411 		       msg);
412 }
413 
414 void
DoSendRrcConnectionReestablishmentReject(uint16_t rnti,LteRrcSap::RrcConnectionReestablishmentReject msg)415 LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg)
416 {
417   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
418 		       &LteUeRrcSapProvider::RecvRrcConnectionReestablishmentReject,
419 		       GetUeRrcSapProvider (rnti),
420 		       msg);
421 }
422 
423 void
DoSendRrcConnectionRelease(uint16_t rnti,LteRrcSap::RrcConnectionRelease msg)424 LteEnbRrcProtocolIdeal::DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg)
425 {
426   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
427 		       &LteUeRrcSapProvider::RecvRrcConnectionRelease,
428 		       GetUeRrcSapProvider (rnti),
429 		       msg);
430 }
431 
432 void
DoSendRrcConnectionReject(uint16_t rnti,LteRrcSap::RrcConnectionReject msg)433 LteEnbRrcProtocolIdeal::DoSendRrcConnectionReject (uint16_t rnti, LteRrcSap::RrcConnectionReject msg)
434 {
435   Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
436 		       &LteUeRrcSapProvider::RecvRrcConnectionReject,
437 		       GetUeRrcSapProvider (rnti),
438 		       msg);
439 }
440 
441 /*
442  * The purpose of LteEnbRrcProtocolIdeal is to avoid encoding
443  * messages. In order to do so, we need to have some form of encoding for
444  * inter-node RRC messages like HandoverPreparationInfo and HandoverCommand. Doing so
445  * directly is not practical (these messages includes a lot of
446  * information elements, so encoding all of them would defeat the
447  * purpose of LteEnbRrcProtocolIdeal. The workaround is to store the
448  * actual message in a global map, so that then we can just encode the
449  * key in a header and send that between eNBs over X2.
450  *
451  */
452 
453 static std::map<uint32_t, LteRrcSap::HandoverPreparationInfo> g_handoverPreparationInfoMsgMap; ///< handover preparation info message map
454 static uint32_t g_handoverPreparationInfoMsgIdCounter = 0; ///< handover preparation info message ID counter
455 
456 /**
457  * This header encodes the map key discussed above. We keep this
458  * private since it should not be used outside this file.
459  *
460  */
461 class IdealHandoverPreparationInfoHeader : public Header
462 {
463 public:
464   /**
465    * Get the message ID function
466    *
467    * \returns the message ID
468    */
469   uint32_t GetMsgId ();
470   /**
471    * Set the message ID function
472    *
473    * \param id the message ID
474    */
475   void SetMsgId (uint32_t id);
476   /**
477    * \brief Get the type ID.
478    * \return the object TypeId
479    */
480   static TypeId GetTypeId (void);
481   virtual TypeId GetInstanceTypeId (void) const;
482   virtual void Print (std::ostream &os) const;
483   virtual uint32_t GetSerializedSize (void) const;
484   virtual void Serialize (Buffer::Iterator start) const;
485   virtual uint32_t Deserialize (Buffer::Iterator start);
486 
487 private:
488   uint32_t m_msgId; ///< message ID
489 };
490 
491 uint32_t
GetMsgId()492 IdealHandoverPreparationInfoHeader::GetMsgId ()
493 {
494   return m_msgId;
495 }
496 
497 void
SetMsgId(uint32_t id)498 IdealHandoverPreparationInfoHeader::SetMsgId (uint32_t id)
499 {
500   m_msgId = id;
501 }
502 
503 
504 TypeId
GetTypeId(void)505 IdealHandoverPreparationInfoHeader::GetTypeId (void)
506 {
507   static TypeId tid = TypeId ("ns3::IdealHandoverPreparationInfoHeader")
508     .SetParent<Header> ()
509     .SetGroupName("Lte")
510     .AddConstructor<IdealHandoverPreparationInfoHeader> ()
511   ;
512   return tid;
513 }
514 
515 TypeId
GetInstanceTypeId(void) const516 IdealHandoverPreparationInfoHeader::GetInstanceTypeId (void) const
517 {
518   return GetTypeId ();
519 }
520 
Print(std::ostream & os) const521 void IdealHandoverPreparationInfoHeader::Print (std::ostream &os)  const
522 {
523   os << " msgId=" << m_msgId;
524 }
525 
GetSerializedSize(void) const526 uint32_t IdealHandoverPreparationInfoHeader::GetSerializedSize (void) const
527 {
528   return 4;
529 }
530 
Serialize(Buffer::Iterator start) const531 void IdealHandoverPreparationInfoHeader::Serialize (Buffer::Iterator start) const
532 {
533   start.WriteU32 (m_msgId);
534 }
535 
Deserialize(Buffer::Iterator start)536 uint32_t IdealHandoverPreparationInfoHeader::Deserialize (Buffer::Iterator start)
537 {
538   m_msgId = start.ReadU32 ();
539   return GetSerializedSize ();
540 }
541 
542 
543 
544 Ptr<Packet>
DoEncodeHandoverPreparationInformation(LteRrcSap::HandoverPreparationInfo msg)545 LteEnbRrcProtocolIdeal::DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg)
546 {
547   uint32_t msgId = ++g_handoverPreparationInfoMsgIdCounter;
548   NS_ASSERT_MSG (g_handoverPreparationInfoMsgMap.find (msgId) == g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " already in use");
549   NS_LOG_INFO (" encoding msgId = " << msgId);
550   g_handoverPreparationInfoMsgMap.insert (std::pair<uint32_t, LteRrcSap::HandoverPreparationInfo> (msgId, msg));
551   IdealHandoverPreparationInfoHeader h;
552   h.SetMsgId (msgId);
553   Ptr<Packet> p = Create<Packet> ();
554   p->AddHeader (h);
555   return p;
556 }
557 
558 LteRrcSap::HandoverPreparationInfo
DoDecodeHandoverPreparationInformation(Ptr<Packet> p)559 LteEnbRrcProtocolIdeal::DoDecodeHandoverPreparationInformation (Ptr<Packet> p)
560 {
561   IdealHandoverPreparationInfoHeader h;
562   p->RemoveHeader (h);
563   uint32_t msgId = h.GetMsgId ();
564   NS_LOG_INFO (" decoding msgId = " << msgId);
565   std::map<uint32_t, LteRrcSap::HandoverPreparationInfo>::iterator it = g_handoverPreparationInfoMsgMap.find (msgId);
566   NS_ASSERT_MSG (it != g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " not found");
567   LteRrcSap::HandoverPreparationInfo msg = it->second;
568   g_handoverPreparationInfoMsgMap.erase (it);
569   return msg;
570 }
571 
572 
573 
574 static std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration> g_handoverCommandMsgMap; ///< handover command message map
575 static uint32_t g_handoverCommandMsgIdCounter = 0; ///< handover command message ID counter
576 
577 /**
578  * This header encodes the map key discussed above. We keep this
579  * private since it should not be used outside this file.
580  *
581  */
582 class IdealHandoverCommandHeader : public Header
583 {
584 public:
585   /**
586    * Get the message ID function
587    *
588    * \returns the message ID
589    */
590   uint32_t GetMsgId ();
591   /**
592    * Set the message ID function
593    *
594    * \param id the message ID
595    */
596   void SetMsgId (uint32_t id);
597   /**
598    * \brief Get the type ID.
599    * \return the object TypeId
600    */
601   static TypeId GetTypeId (void);
602   virtual TypeId GetInstanceTypeId (void) const;
603   virtual void Print (std::ostream &os) const;
604   virtual uint32_t GetSerializedSize (void) const;
605   virtual void Serialize (Buffer::Iterator start) const;
606   virtual uint32_t Deserialize (Buffer::Iterator start);
607 
608 private:
609   uint32_t m_msgId; ///< message ID
610 };
611 
612 uint32_t
GetMsgId()613 IdealHandoverCommandHeader::GetMsgId ()
614 {
615   return m_msgId;
616 }
617 
618 void
SetMsgId(uint32_t id)619 IdealHandoverCommandHeader::SetMsgId (uint32_t id)
620 {
621   m_msgId = id;
622 }
623 
624 
625 TypeId
GetTypeId(void)626 IdealHandoverCommandHeader::GetTypeId (void)
627 {
628   static TypeId tid = TypeId ("ns3::IdealHandoverCommandHeader")
629     .SetParent<Header> ()
630     .SetGroupName("Lte")
631     .AddConstructor<IdealHandoverCommandHeader> ()
632   ;
633   return tid;
634 }
635 
636 TypeId
GetInstanceTypeId(void) const637 IdealHandoverCommandHeader::GetInstanceTypeId (void) const
638 {
639   return GetTypeId ();
640 }
641 
Print(std::ostream & os) const642 void IdealHandoverCommandHeader::Print (std::ostream &os)  const
643 {
644   os << " msgId=" << m_msgId;
645 }
646 
GetSerializedSize(void) const647 uint32_t IdealHandoverCommandHeader::GetSerializedSize (void) const
648 {
649   return 4;
650 }
651 
Serialize(Buffer::Iterator start) const652 void IdealHandoverCommandHeader::Serialize (Buffer::Iterator start) const
653 {
654   start.WriteU32 (m_msgId);
655 }
656 
Deserialize(Buffer::Iterator start)657 uint32_t IdealHandoverCommandHeader::Deserialize (Buffer::Iterator start)
658 {
659   m_msgId = start.ReadU32 ();
660   return GetSerializedSize ();
661 }
662 
663 
664 
665 Ptr<Packet>
DoEncodeHandoverCommand(LteRrcSap::RrcConnectionReconfiguration msg)666 LteEnbRrcProtocolIdeal::DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg)
667 {
668   uint32_t msgId = ++g_handoverCommandMsgIdCounter;
669   NS_ASSERT_MSG (g_handoverCommandMsgMap.find (msgId) == g_handoverCommandMsgMap.end (), "msgId " << msgId << " already in use");
670   NS_LOG_INFO (" encoding msgId = " << msgId);
671   g_handoverCommandMsgMap.insert (std::pair<uint32_t, LteRrcSap::RrcConnectionReconfiguration> (msgId, msg));
672   IdealHandoverCommandHeader h;
673   h.SetMsgId (msgId);
674   Ptr<Packet> p = Create<Packet> ();
675   p->AddHeader (h);
676   return p;
677 }
678 
679 LteRrcSap::RrcConnectionReconfiguration
DoDecodeHandoverCommand(Ptr<Packet> p)680 LteEnbRrcProtocolIdeal::DoDecodeHandoverCommand (Ptr<Packet> p)
681 {
682   IdealHandoverCommandHeader h;
683   p->RemoveHeader (h);
684   uint32_t msgId = h.GetMsgId ();
685   NS_LOG_INFO (" decoding msgId = " << msgId);
686   std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration>::iterator it = g_handoverCommandMsgMap.find (msgId);
687   NS_ASSERT_MSG (it != g_handoverCommandMsgMap.end (), "msgId " << msgId << " not found");
688   LteRrcSap::RrcConnectionReconfiguration msg = it->second;
689   g_handoverCommandMsgMap.erase (it);
690   return msg;
691 }
692 
693 
694 
695 
696 
697 } // namespace ns3
698