OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2011, 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 * Budiarto Herman <budiarto.herman@magister.fi> |
| 20 */ |
| 21 |
| 22 #include "nist-lte-ue-rrc.h" |
| 23 |
| 24 #include <ns3/fatal-error.h> |
| 25 #include <ns3/log.h> |
| 26 #include <ns3/object-map.h> |
| 27 #include <ns3/object-factory.h> |
| 28 #include <ns3/simulator.h> |
| 29 |
| 30 #include <ns3/nist-lte-rlc.h> |
| 31 #include <ns3/nist-lte-rlc-tm.h> |
| 32 #include <ns3/nist-lte-rlc-um.h> |
| 33 #include <ns3/nist-lte-rlc-am.h> |
| 34 #include <ns3/nist-lte-pdcp.h> |
| 35 #include <ns3/nist-lte-radio-bearer-info.h> |
| 36 #include <ns3/nist-sl-pool.h> |
| 37 #include <ns3/random-variable-stream.h> |
| 38 |
| 39 #include <cmath> |
| 40 |
| 41 namespace ns3 { |
| 42 |
| 43 NS_LOG_COMPONENT_DEFINE ("NistLteUeRrc"); |
| 44 |
| 45 /////////////////////////////////////////// |
| 46 // LteEnbRrcSl |
| 47 /////////////////////////////////////////// |
| 48 |
| 49 NS_OBJECT_ENSURE_REGISTERED (LteUeRrcSl); |
| 50 |
| 51 LteUeRrcSl::LteUeRrcSl () |
| 52 : m_slEnabled (false) |
| 53 { |
| 54 ·· |
| 55 } |
| 56 |
| 57 void |
| 58 LteUeRrcSl::DoInitialize () |
| 59 { |
| 60 |
| 61 |
| 62 } |
| 63 |
| 64 LteUeRrcSl::~LteUeRrcSl (void) |
| 65 { |
| 66 } |
| 67 ·· |
| 68 void |
| 69 LteUeRrcSl::DoDispose () |
| 70 { |
| 71 ···· |
| 72 } |
| 73 |
| 74 TypeId LteUeRrcSl::GetTypeId (void) |
| 75 { |
| 76 static TypeId tid = TypeId ("ns3::LteUeRrcSl") |
| 77 .SetParent<Object> () |
| 78 .AddConstructor<LteUeRrcSl> () |
| 79 ···· |
| 80 ; |
| 81 return tid; |
| 82 } |
| 83 |
| 84 /** |
| 85 * \brief makes a copy of the sidelink configuration |
| 86 * \return a copy of the sidelink configuration |
| 87 */ |
| 88 Ptr<LteUeRrcSl> |
| 89 LteUeRrcSl::Copy () |
| 90 { |
| 91 NS_LOG_FUNCTION (this); |
| 92 Ptr<LteUeRrcSl> copy = CreateObject<LteUeRrcSl> (); |
| 93 //copy internal values |
| 94 copy->m_slEnabled = m_slEnabled; |
| 95 copy->m_slMap = m_slMap; |
| 96 return copy; |
| 97 } |
| 98 |
| 99 void |
| 100 LteUeRrcSl::SetSlEnabled (bool status) |
| 101 { |
| 102 NS_LOG_FUNCTION (this); |
| 103 m_slEnabled = status; |
| 104 } |
| 105 ···· |
| 106 bool |
| 107 LteUeRrcSl::IsSlEnabled () |
| 108 { |
| 109 NS_LOG_FUNCTION (this); |
| 110 return m_slEnabled; |
| 111 } |
| 112 |
| 113 void |
| 114 LteUeRrcSl::SetDiscEnabled (bool status) |
| 115 { |
| 116 NS_LOG_FUNCTION (this); |
| 117 m_discEnabled = status; |
| 118 } |
| 119 ···· |
| 120 bool |
| 121 LteUeRrcSl::IsDiscEnabled () |
| 122 { |
| 123 NS_LOG_FUNCTION (this); |
| 124 return m_discEnabled; |
| 125 } |
| 126 |
| 127 void |
| 128 LteUeRrcSl::SetSlPreconfiguration (NistLteRrcSap::SlPreconfiguration preconfigur
ation) |
| 129 { |
| 130 NS_LOG_FUNCTION (this); |
| 131 m_preconfiguration = preconfiguration; |
| 132 } |
| 133 |
| 134 NistLteRrcSap::SlPreconfiguration |
| 135 LteUeRrcSl::GetSlPreconfiguration () |
| 136 { |
| 137 NS_LOG_FUNCTION (this); |
| 138 return m_preconfiguration; |
| 139 } |
| 140 |
| 141 void |
| 142 LteUeRrcSl::SetSourceL2Id (uint32_t src) |
| 143 { |
| 144 NS_LOG_FUNCTION (this); |
| 145 m_sourceL2Id = src; |
| 146 } |
| 147 ·· |
| 148 bool |
| 149 LteUeRrcSl::IsTxInterested () |
| 150 { |
| 151 NS_LOG_FUNCTION (this); |
| 152 |
| 153 //Loop through each bearer to see if one is interested to transmit |
| 154 std::map <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> > >::i
terator srcIt = m_slrbMap.find (m_sourceL2Id); |
| 155 if (srcIt == m_slrbMap.end ()) { |
| 156 return false; |
| 157 }· |
| 158 return m_slrbMap[m_sourceL2Id].size () >0; |
| 159 } |
| 160 |
| 161 bool |
| 162 LteUeRrcSl::IsRxInterested () |
| 163 { |
| 164 NS_LOG_FUNCTION (this); |
| 165 ·· |
| 166 return m_rxGroup.size() > 0; |
| 167 } |
| 168 |
| 169 bool |
| 170 LteUeRrcSl::IsMonitoringInterested () |
| 171 { |
| 172 NS_LOG_FUNCTION (this); |
| 173 return m_monitorApps.size () > 0; |
| 174 } |
| 175 |
| 176 bool |
| 177 LteUeRrcSl::IsAnnouncingInterested () |
| 178 { |
| 179 NS_LOG_FUNCTION (this); |
| 180 return m_announceApps.size () > 0; |
| 181 } |
| 182 |
| 183 std::list<uint32_t> |
| 184 LteUeRrcSl::GetTxDestinations () |
| 185 { |
| 186 std::list<uint32_t> destinations; |
| 187 |
| 188 //Loop through each bearer to see if one is interested to transmit |
| 189 std::map <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> > >::i
terator srcIt = m_slrbMap.find (m_sourceL2Id); |
| 190 if (srcIt != m_slrbMap.end ()) { |
| 191 //Loop through each bearer to see if one is interested to transmit |
| 192 std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >::iterator it; |
| 193 for (it = m_slrbMap[m_sourceL2Id].begin(); it != m_slrbMap[m_sourceL2Id].end
(); it++) { |
| 194 destinations.push_back (it->second->m_destinationL2Id); |
| 195 } |
| 196 } |
| 197 return destinations; |
| 198 } |
| 199 |
| 200 uint8_t· |
| 201 LteUeRrcSl::GetDiscTxResources () |
| 202 { |
| 203 return m_discTxResources; |
| 204 } |
| 205 |
| 206 void |
| 207 LteUeRrcSl::SetDiscTxResources (uint8_t nb) |
| 208 { |
| 209 m_discTxResources = nb;·· |
| 210 } |
| 211 |
| 212 uint16_t· |
| 213 LteUeRrcSl::GetDiscInterFreq () |
| 214 { |
| 215 return m_discInterFreq; |
| 216 } |
| 217 void |
| 218 LteUeRrcSl::SetDiscInterFreq (uint16_t ulEarfcn) |
| 219 { |
| 220 m_discInterFreq = ulEarfcn; |
| 221 } |
| 222 |
| 223 bool |
| 224 LteUeRrcSl::AddSidelinkRadioBearer (Ptr<LteSidelinkRadioBearerInfo> slb) |
| 225 { |
| 226 std::map <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> > >::i
terator srcIt = m_slrbMap.find (slb->m_sourceL2Id); |
| 227 if (srcIt == m_slrbMap.end ()) { |
| 228 //must insert map |
| 229 std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> > empty; |
| 230 ···· |
| 231 m_slrbMap.insert (std::pair <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRa
dioBearerInfo> > > (slb->m_sourceL2Id, empty)); |
| 232 NS_LOG_LOGIC ("First SLRB for source " << slb->m_sourceL2Id); |
| 233 } |
| 234 |
| 235 std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >::iterator groupIt = m_sl
rbMap[slb->m_sourceL2Id].find (slb->m_destinationL2Id); |
| 236 NS_ASSERT (groupIt == m_slrbMap[slb->m_sourceL2Id].end()); |
| 237 NS_LOG_LOGIC ("Adding SLRB " << slb->m_sourceL2Id << "->" << slb->m_destinatio
nL2Id); |
| 238 m_slrbMap[slb->m_sourceL2Id].insert (std::pair<uint32_t,Ptr<LteSidelinkRadioBe
arerInfo> > (slb->m_destinationL2Id, slb)); |
| 239 |
| 240 return true; |
| 241 } |
| 242 |
| 243 bool |
| 244 LteUeRrcSl::DeleteSidelinkRadioBearer (uint32_t src, uint32_t group) |
| 245 { |
| 246 bool deleted = m_slrbMap[src].erase (group) >0; |
| 247 if (m_slrbMap[src].size() == 0) { |
| 248 //can delete the source as well |
| 249 m_slrbMap.erase (src); |
| 250 } |
| 251 //remove from receiving group if present |
| 252 m_rxGroup.remove (group); |
| 253 ·· |
| 254 return deleted; |
| 255 } |
| 256 ·· |
| 257 Ptr<LteSidelinkRadioBearerInfo> |
| 258 LteUeRrcSl::GetSidelinkRadioBearer (uint32_t src, uint32_t group) |
| 259 { |
| 260 Ptr<LteSidelinkRadioBearerInfo> slrb = NULL; |
| 261 ·· |
| 262 NS_LOG_LOGIC ("Searching SLRB " << src << "->" << group); |
| 263 |
| 264 // //Print list of SLRB |
| 265 // { |
| 266 // NS_LOG_LOGIC ("Configured SLRBs ");· |
| 267 // std::map <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >
>::iterator srcIt; |
| 268 // for (srcIt = m_slrbMap.begin (); srcIt != m_slrbMap.end () ; srcIt++) { |
| 269 // std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >::iterator dstIt; |
| 270 // for (dstIt = srcIt->second.begin() ; dstIt != srcIt->second.end (); dst
It++) { |
| 271 // NS_LOG_LOGIC ("SLRB " << dstIt->second->m_sourceL2Id << "->" << dstIt
->second->m_groupL2Address); |
| 272 // } |
| 273 // } |
| 274 // } |
| 275 ·· |
| 276 std::map <uint32_t, std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> > >::i
terator srcIt = m_slrbMap.find (src); |
| 277 if (srcIt != m_slrbMap.end ()) { |
| 278 std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >::iterator srcIt2 = (*s
rcIt).second.find (group); |
| 279 if (srcIt2 != (*srcIt).second.end()) { |
| 280 slrb = m_slrbMap[src][group];······ |
| 281 } |
| 282 } |
| 283 return slrb; |
| 284 } |
| 285 |
| 286 Ptr<LteSidelinkRadioBearerInfo> |
| 287 LteUeRrcSl::GetSidelinkRadioBearer (uint32_t group) |
| 288 { |
| 289 return GetSidelinkRadioBearer (m_sourceL2Id, group); |
| 290 } |
| 291 |
| 292 void· |
| 293 LteUeRrcSl::AddDiscoveryApps (std::list<uint32_t> apps, bool rxtx) |
| 294 { |
| 295 for (std::list<uint32_t>::iterator it = apps.begin (); it != apps.end (); ++it
) |
| 296 { |
| 297 if (rxtx) |
| 298 { |
| 299 m_announceApps.push_back (*it); |
| 300 } |
| 301 else· |
| 302 { |
| 303 m_monitorApps.push_back (*it); |
| 304 } |
| 305 } |
| 306 } |
| 307 |
| 308 |
| 309 void· |
| 310 LteUeRrcSl::RemoveDiscoveryApps (std::list<uint32_t> apps, bool rxtx) |
| 311 { |
| 312 for (std::list<uint32_t>::iterator it = apps.begin (); it != apps.end (); ++it
) |
| 313 { |
| 314 if (rxtx) |
| 315 { |
| 316 m_announceApps.remove (*it); |
| 317 } |
| 318 else· |
| 319 { |
| 320 m_monitorApps.remove (*it); |
| 321 } |
| 322 } |
| 323 } |
| 324 |
| 325 void |
| 326 LteUeRrcSl::RecordTransmissionOfSidelinkUeInformation () |
| 327 { |
| 328 m_lastSidelinkUeInformationTime = Simulator::Now (); |
| 329 } |
| 330 |
| 331 double |
| 332 LteUeRrcSl::GetTimeSinceLastTransmissionOfSidelinkUeInformation () |
| 333 { |
| 334 return (Simulator::Now() - m_lastSidelinkUeInformationTime).GetSeconds(); |
| 335 } |
| 336 |
| 337 uint8_t |
| 338 LteUeRrcSl::GetNextLcid () |
| 339 { |
| 340 //find unused the LCID |
| 341 bool found = true; |
| 342 uint8_t lcid; |
| 343 ·· |
| 344 for (lcid = 1; lcid < 11; lcid++) { |
| 345 found = false; |
| 346 std::map <uint32_t, Ptr<LteSidelinkRadioBearerInfo> >::iterator it; |
| 347 for (it = m_slrbMap[m_sourceL2Id].begin(); it != m_slrbMap[m_sourceL2Id].end
(); it++) { |
| 348 if (it->second->m_logicalChannelIdentity == lcid) { |
| 349 found = true; |
| 350 break; |
| 351 } |
| 352 } |
| 353 if (!found) { |
| 354 break; //avoid increasing lcid |
| 355 } |
| 356 } |
| 357 NS_ASSERT (!found); |
| 358 return lcid; |
| 359 } |
| 360 |
| 361 bool |
| 362 LteUeRrcSl::IsCellBroadcastingSIB18 (uint16_t cellId) |
| 363 { |
| 364 std::map <uint16_t, LteSlCellConfiguration>::iterator it = m_slMap.find (cellI
d); |
| 365 return (it != m_slMap.end() && it->second.haveSib18); |
| 366 } |
| 367 |
| 368 bool |
| 369 LteUeRrcSl::IsCellBroadcastingSIB19 (uint16_t cellId) |
| 370 { |
| 371 std::map <uint16_t, LteSlCellConfiguration>::iterator it = m_slMap.find (cellI
d); |
| 372 return (it != m_slMap.end() && it->second.haveSib19); |
| 373 } |
| 374 |
| 375 ///////////////////////////// |
| 376 // CMAC SAP forwarder |
| 377 ///////////////////////////// |
| 378 |
| 379 class NistUeMemberLteUeCmacSapUser : public NistLteUeCmacSapUser |
| 380 { |
| 381 public: |
| 382 NistUeMemberLteUeCmacSapUser (NistLteUeRrc* rrc); |
| 383 |
| 384 virtual void SetTemporaryCellRnti (uint16_t rnti); |
| 385 virtual void NotifyRandomAccessSuccessful (); |
| 386 virtual void NotifyRandomAccessFailed (); |
| 387 //communication |
| 388 virtual void NotifySidelinkReception (uint8_t lcId, uint32_t srcL2Id, uint32_t
dstL2Id); |
| 389 virtual void NotifyMacHasSlDataToSend (); |
| 390 virtual void NotifyMacHasNotSlDataToSend (); |
| 391 //discovery |
| 392 virtual void NotifyDiscoveryReception (Ptr<NistLteControlMessage> msg); |
| 393 |
| 394 private: |
| 395 NistLteUeRrc* m_rrc; |
| 396 }; |
| 397 |
| 398 NistUeMemberLteUeCmacSapUser::NistUeMemberLteUeCmacSapUser (NistLteUeRrc* rrc) |
| 399 : m_rrc (rrc) |
| 400 { |
| 401 } |
| 402 |
| 403 void |
| 404 NistUeMemberLteUeCmacSapUser::SetTemporaryCellRnti (uint16_t rnti) |
| 405 { |
| 406 m_rrc->DoSetTemporaryCellRnti (rnti); |
| 407 } |
| 408 |
| 409 |
| 410 void |
| 411 NistUeMemberLteUeCmacSapUser::NotifyRandomAccessSuccessful () |
| 412 { |
| 413 m_rrc->DoNotifyRandomAccessSuccessful (); |
| 414 } |
| 415 |
| 416 void |
| 417 NistUeMemberLteUeCmacSapUser::NotifyRandomAccessFailed () |
| 418 { |
| 419 m_rrc->DoNotifyRandomAccessFailed (); |
| 420 } |
| 421 |
| 422 void |
| 423 NistUeMemberLteUeCmacSapUser::NotifySidelinkReception (uint8_t lcId, uint32_t sr
cL2Id, uint32_t dstL2Id) |
| 424 { |
| 425 m_rrc->DoNotifySidelinkReception (lcId, srcL2Id, dstL2Id); |
| 426 } |
| 427 |
| 428 void |
| 429 NistUeMemberLteUeCmacSapUser::NotifyMacHasSlDataToSend () |
| 430 { |
| 431 m_rrc->DoNotifyMacHasSlDataToSend (); |
| 432 } |
| 433 |
| 434 void |
| 435 NistUeMemberLteUeCmacSapUser::NotifyMacHasNotSlDataToSend () |
| 436 { |
| 437 m_rrc->DoNotifyMacHasNotSlDataToSend (); |
| 438 } |
| 439 |
| 440 void |
| 441 NistUeMemberLteUeCmacSapUser::NotifyDiscoveryReception (Ptr<NistLteControlMessag
e> msg) |
| 442 { |
| 443 m_rrc->DoNotifyDiscoveryReception (msg); |
| 444 } |
| 445 |
| 446 /// Map each of UE RRC states to its string representation. |
| 447 static const std::string g_ueRrcStateName[NistLteUeRrc::NUM_STATES] = |
| 448 { |
| 449 "IDLE_START", |
| 450 "IDLE_CELL_SEARCH", |
| 451 "IDLE_WAIT_MIB_SIB1", |
| 452 "IDLE_WAIT_MIB", |
| 453 "IDLE_WAIT_SIB1", |
| 454 "IDLE_CAMPED_NORMALLY", |
| 455 "IDLE_WAIT_SIB2", |
| 456 "IDLE_RANDOM_ACCESS", |
| 457 "IDLE_CONNECTING", |
| 458 "CONNECTED_NORMALLY", |
| 459 "CONNECTED_HANDOVER", |
| 460 "CONNECTED_PHY_PROBLEM", |
| 461 "CONNECTED_REESTABLISHING" |
| 462 }; |
| 463 |
| 464 /** |
| 465 * \param s The UE RRC state. |
| 466 * \return The string representation of the given state. |
| 467 */ |
| 468 static const std::string & ToString (NistLteUeRrc::State s) |
| 469 { |
| 470 return g_ueRrcStateName[s]; |
| 471 } |
| 472 |
| 473 |
| 474 ///////////////////////////// |
| 475 // ue RRC methods |
| 476 ///////////////////////////// |
| 477 |
| 478 NS_OBJECT_ENSURE_REGISTERED (NistLteUeRrc); |
| 479 |
| 480 |
| 481 NistLteUeRrc::NistLteUeRrc () |
| 482 : m_cphySapProvider (0), |
| 483 m_cmacSapProvider (0), |
| 484 m_rrcSapUser (0), |
| 485 m_macSapProvider (0), |
| 486 m_asSapUser (0), |
| 487 m_state (IDLE_START), |
| 488 m_imsi (0), |
| 489 m_rnti (0), |
| 490 m_cellId (0), |
| 491 m_useRlcSm (true), |
| 492 m_connectionPending (false), |
| 493 m_hasReceivedMib (false), |
| 494 m_hasReceivedSib1 (false), |
| 495 m_hasReceivedSib2 (false), |
| 496 m_csgWhiteList (0), |
| 497 m_sidelinkConfiguration (0), |
| 498 m_slssTransmissionActive(false), |
| 499 m_txSlSyncOffsetIndicator(0), |
| 500 m_hasSyncRef (false), |
| 501 m_inCoverage(false), |
| 502 m_slssId(0), |
| 503 m_currSubframeNo(0), |
| 504 m_currFrameNo(0), |
| 505 m_hasDataToTransmit(false), |
| 506 m_inInnerCellOfSyncRef(false), |
| 507 m_slssTxTime(Seconds(0)) |
| 508 { |
| 509 NS_LOG_FUNCTION (this); |
| 510 m_cphySapUser = new NistMemberLteUeCphySapUser<NistLteUeRrc> (this); |
| 511 m_cmacSapUser = new NistUeMemberLteUeCmacSapUser (this); |
| 512 m_rrcSapProvider = new NistMemberLteUeRrcSapProvider<NistLteUeRrc> (this); |
| 513 m_drbPdcpSapUser = new NistLtePdcpSpecificLtePdcpSapUser<NistLteUeRrc> (this); |
| 514 m_asSapProvider = new NistMemberLteAsSapProvider<NistLteUeRrc> (this); |
| 515 } |
| 516 |
| 517 |
| 518 NistLteUeRrc::~NistLteUeRrc () |
| 519 { |
| 520 NS_LOG_FUNCTION (this); |
| 521 } |
| 522 |
| 523 void |
| 524 NistLteUeRrc::DoDispose () |
| 525 { |
| 526 NS_LOG_FUNCTION (this); |
| 527 delete m_cphySapUser; |
| 528 delete m_cmacSapUser; |
| 529 delete m_rrcSapProvider; |
| 530 delete m_drbPdcpSapUser; |
| 531 delete m_asSapProvider; |
| 532 m_drbMap.clear (); |
| 533 } |
| 534 |
| 535 TypeId |
| 536 NistLteUeRrc::GetTypeId (void) |
| 537 { |
| 538 static TypeId tid = TypeId ("ns3::NistLteUeRrc") |
| 539 .SetParent<Object> () |
| 540 .AddConstructor<NistLteUeRrc> () |
| 541 .AddAttribute ("DataRadioBearerMap", "List of UE RadioNistBearerInfo for Dat
a Radio Bearers by LCID.", |
| 542 ObjectMapValue (), |
| 543 MakeObjectMapAccessor (&NistLteUeRrc::m_drbMap), |
| 544 MakeObjectMapChecker<LteDataRadioNistBearerInfo> ()) |
| 545 .AddAttribute ("Srb0", "SignalingRadioNistBearerInfo for SRB0", |
| 546 PointerValue (), |
| 547 MakePointerAccessor (&NistLteUeRrc::m_srb0), |
| 548 MakePointerChecker<LteSignalingRadioNistBearerInfo> ()) |
| 549 .AddAttribute ("Srb1", "SignalingRadioNistBearerInfo for SRB1", |
| 550 PointerValue (), |
| 551 MakePointerAccessor (&NistLteUeRrc::m_srb1), |
| 552 MakePointerChecker<LteSignalingRadioNistBearerInfo> ()) |
| 553 .AddAttribute ("CellId", |
| 554 "Serving cell identifier", |
| 555 UintegerValue (0), // unused, read-only attribute |
| 556 MakeUintegerAccessor (&NistLteUeRrc::GetCellId), |
| 557 MakeUintegerChecker<uint16_t> ()) |
| 558 .AddAttribute ("C-RNTI", |
| 559 "Cell Radio Network Temporary Identifier", |
| 560 UintegerValue (0), // unused, read-only attribute |
| 561 MakeUintegerAccessor (&NistLteUeRrc::GetRnti), |
| 562 MakeUintegerChecker<uint16_t> ()) |
| 563 .AddAttribute ("T300", |
| 564 "Timer for the RRC Connection Establishment procedure " |
| 565 "(i.e., the procedure is deemed as failed if it takes longer
than this)", |
| 566 TimeValue (MilliSeconds (100)), |
| 567 MakeTimeAccessor (&NistLteUeRrc::m_t300), |
| 568 MakeTimeChecker ()) |
| 569 //Add accessor to sidelink configuration |
| 570 .AddAttribute ("SidelinkConfiguration", |
| 571 "The sidelink configuration associated to this NistLtePhy", |
| 572 PointerValue (), |
| 573 MakePointerAccessor (&NistLteUeRrc::m_sidelinkConfiguration), |
| 574 MakePointerChecker <LteUeRrcSl> ()) |
| 575 .AddTraceSource ("MibReceived", |
| 576 "trace fired upon reception of Master Information Block", |
| 577 MakeTraceSourceAccessor (&NistLteUeRrc::m_mibReceivedTrace)
, |
| 578 "ns3::NistLteUeRrc::MibSibHandoverTracedCallback") |
| 579 .AddTraceSource ("Sib1Received", |
| 580 "trace fired upon reception of System Information Block Typ
e 1", |
| 581 MakeTraceSourceAccessor (&NistLteUeRrc::m_sib1ReceivedTrace
), |
| 582 "ns3::NistLteUeRrc::MibSibHandoverTracedCallback") |
| 583 .AddTraceSource ("Sib2Received", |
| 584 "trace fired upon reception of System Information Block Typ
e 2", |
| 585 MakeTraceSourceAccessor (&NistLteUeRrc::m_sib2ReceivedTrace
), |
| 586 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 587 .AddTraceSource ("StateTransition", |
| 588 "trace fired upon every UE RRC state transition", |
| 589 MakeTraceSourceAccessor (&NistLteUeRrc::m_stateTransitionTr
ace), |
| 590 "ns3::NistLteUeRrc::StateTracedCallback") |
| 591 .AddTraceSource ("InitialCellSelectionEndOk", |
| 592 "trace fired upon successful initial cell selection procedu
re", |
| 593 MakeTraceSourceAccessor (&NistLteUeRrc::m_initialCellSelect
ionEndOkTrace), |
| 594 "ns3::NistLteUeRrc::CellSelectionTracedCallback") |
| 595 .AddTraceSource ("InitialCellSelectionEndError", |
| 596 "trace fired upon failed initial cell selection procedure", |
| 597 MakeTraceSourceAccessor (&NistLteUeRrc::m_initialCellSelect
ionEndErrorTrace), |
| 598 "ns3::NistLteUeRrc::CellSelectionTracedCallback") |
| 599 .AddTraceSource ("RandomAccessSuccessful", |
| 600 "trace fired upon successful completion of the random acces
s procedure", |
| 601 MakeTraceSourceAccessor (&NistLteUeRrc::m_randomAccessSucce
ssfulTrace), |
| 602 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 603 .AddTraceSource ("RandomAccessError", |
| 604 "trace fired upon failure of the random access procedure", |
| 605 MakeTraceSourceAccessor (&NistLteUeRrc::m_randomAccessError
Trace), |
| 606 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 607 .AddTraceSource ("ConnectionEstablished", |
| 608 "trace fired upon successful RRC connection establishment", |
| 609 MakeTraceSourceAccessor (&NistLteUeRrc::m_connectionEstabli
shedTrace), |
| 610 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 611 .AddTraceSource ("ConnectionTimeout", |
| 612 "trace fired upon timeout RRC connection establishment beca
use of T300", |
| 613 MakeTraceSourceAccessor (&NistLteUeRrc::m_connectionTimeout
Trace), |
| 614 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 615 .AddTraceSource ("ConnectionReconfiguration", |
| 616 "trace fired upon RRC connection reconfiguration", |
| 617 MakeTraceSourceAccessor (&NistLteUeRrc::m_connectionReconfi
gurationTrace), |
| 618 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 619 .AddTraceSource ("HandoverStart", |
| 620 "trace fired upon start of a handover procedure", |
| 621 MakeTraceSourceAccessor (&NistLteUeRrc::m_handoverStartTrac
e), |
| 622 "ns3::NistLteUeRrc::MibSibHandoverTracedCallback") |
| 623 .AddTraceSource ("HandoverEndOk", |
| 624 "trace fired upon successful termination of a handover proc
edure", |
| 625 MakeTraceSourceAccessor (&NistLteUeRrc::m_handoverEndOkTrac
e), |
| 626 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 627 .AddTraceSource ("HandoverEndError", |
| 628 "trace fired upon failure of a handover procedure", |
| 629 MakeTraceSourceAccessor (&NistLteUeRrc::m_handoverEndErrorT
race), |
| 630 "ns3::NistLteUeRrc::ImsiCidRntiTracedCallback") |
| 631 .AddAttribute ("UeSlssTransmissionEnabled", |
| 632 "If True, the UE transmits SLSSs when required as part of the sidel
ink synchronization protocol", |
| 633 BooleanValue(false), |
| 634 MakeBooleanAccessor (&NistLteUeRrc::m_slssTransmissionEnabled), |
| 635 MakeBooleanChecker()) |
| 636 .AddAttribute ("MinSrsrp", |
| 637 "The minimum S-RSRP required to consider a SyncRef detectable", |
| 638 DoubleValue(-125), |
| 639 MakeDoubleAccessor (&NistLteUeRrc::m_minSrsrp), |
| 640 MakeDoubleChecker<double>()) |
| 641 .AddTraceSource ("ChangeOfSyncRef", |
| 642 "trace fired upon report of a change of SyncRef", |
| 643 MakeTraceSourceAccessor (&NistLteUeRrc::m_ChangeOfSyncRefTr
ace), |
| 644 "ns3::NistLteUeRrc::ChangeOfSyncRefTracedCallback") |
| 645 .AddTraceSource ("SendSLSS", |
| 646 "trace fired upon send of a SLSS", |
| 647 MakeTraceSourceAccessor (&NistLteUeRrc::m_SendSlssTrace), |
| 648 "ns3::NistLteUeRrc::SendSLSSTracedCallback") |
| 649 // Added to trace the reception of discovery message |
| 650 .AddTraceSource ("DiscoveryMonitoring", |
| 651 "trace to track the monitoring of discovery messages", |
| 652 MakeTraceSourceAccessor (&NistLteUeRrc::m_discoveryMonitori
ngTrace), |
| 653 "ns3::NistLteUeRrc::DiscoveryMonitoringTracedCallback") |
| 654 ; |
| 655 return tid; |
| 656 } |
| 657 |
| 658 |
| 659 void |
| 660 NistLteUeRrc::SetNistLteUeCphySapProvider (NistLteUeCphySapProvider * s) |
| 661 { |
| 662 NS_LOG_FUNCTION (this << s); |
| 663 m_cphySapProvider = s; |
| 664 } |
| 665 |
| 666 NistLteUeCphySapUser* |
| 667 NistLteUeRrc::GetNistLteUeCphySapUser () |
| 668 { |
| 669 NS_LOG_FUNCTION (this); |
| 670 return m_cphySapUser; |
| 671 } |
| 672 |
| 673 void |
| 674 NistLteUeRrc::SetNistLteUeCmacSapProvider (NistLteUeCmacSapProvider * s) |
| 675 { |
| 676 NS_LOG_FUNCTION (this << s); |
| 677 m_cmacSapProvider = s; |
| 678 } |
| 679 |
| 680 NistLteUeCmacSapUser* |
| 681 NistLteUeRrc::GetNistLteUeCmacSapUser () |
| 682 { |
| 683 NS_LOG_FUNCTION (this); |
| 684 return m_cmacSapUser; |
| 685 } |
| 686 |
| 687 void |
| 688 NistLteUeRrc::SetNistLteUeRrcSapUser (NistLteUeRrcSapUser * s) |
| 689 { |
| 690 NS_LOG_FUNCTION (this << s); |
| 691 m_rrcSapUser = s; |
| 692 } |
| 693 |
| 694 NistLteUeRrcSapProvider* |
| 695 NistLteUeRrc::GetNistLteUeRrcSapProvider () |
| 696 { |
| 697 NS_LOG_FUNCTION (this); |
| 698 return m_rrcSapProvider; |
| 699 } |
| 700 |
| 701 void |
| 702 NistLteUeRrc::SetNistLteMacSapProvider (NistLteMacSapProvider * s) |
| 703 { |
| 704 NS_LOG_FUNCTION (this << s); |
| 705 m_macSapProvider = s; |
| 706 } |
| 707 |
| 708 void |
| 709 NistLteUeRrc::SetAsSapUser (NistLteAsSapUser* s) |
| 710 { |
| 711 m_asSapUser = s; |
| 712 } |
| 713 |
| 714 NistLteAsSapProvider*· |
| 715 NistLteUeRrc::GetAsSapProvider () |
| 716 { |
| 717 return m_asSapProvider; |
| 718 } |
| 719 |
| 720 void· |
| 721 NistLteUeRrc::SetImsi (uint64_t imsi) |
| 722 { |
| 723 NS_LOG_FUNCTION (this << imsi); |
| 724 m_imsi = imsi; |
| 725 } |
| 726 |
| 727 uint64_t |
| 728 NistLteUeRrc::GetImsi (void) const |
| 729 { |
| 730 return m_imsi; |
| 731 } |
| 732 |
| 733 uint16_t |
| 734 NistLteUeRrc::GetRnti () const |
| 735 { |
| 736 NS_LOG_FUNCTION (this); |
| 737 return m_rnti; |
| 738 } |
| 739 |
| 740 uint16_t |
| 741 NistLteUeRrc::GetCellId () const |
| 742 { |
| 743 NS_LOG_FUNCTION (this); |
| 744 return m_cellId; |
| 745 } |
| 746 |
| 747 |
| 748 uint8_t· |
| 749 NistLteUeRrc::GetUlBandwidth () const |
| 750 { |
| 751 NS_LOG_FUNCTION (this); |
| 752 return m_ulBandwidth; |
| 753 } |
| 754 |
| 755 uint8_t· |
| 756 NistLteUeRrc::GetDlBandwidth () const |
| 757 { |
| 758 NS_LOG_FUNCTION (this); |
| 759 return m_dlBandwidth; |
| 760 } |
| 761 |
| 762 uint16_t |
| 763 NistLteUeRrc::GetDlEarfcn () const |
| 764 { |
| 765 return m_dlEarfcn; |
| 766 } |
| 767 |
| 768 uint16_t· |
| 769 NistLteUeRrc::GetUlEarfcn () const |
| 770 { |
| 771 NS_LOG_FUNCTION (this); |
| 772 return m_ulEarfcn; |
| 773 } |
| 774 |
| 775 NistLteUeRrc::State |
| 776 NistLteUeRrc::GetState (void) const |
| 777 { |
| 778 NS_LOG_FUNCTION (this); |
| 779 return m_state; |
| 780 } |
| 781 |
| 782 void |
| 783 NistLteUeRrc::SetUseRlcSm (bool val)· |
| 784 { |
| 785 NS_LOG_FUNCTION (this); |
| 786 m_useRlcSm = val; |
| 787 } |
| 788 |
| 789 |
| 790 void |
| 791 NistLteUeRrc::DoInitialize (void) |
| 792 { |
| 793 NS_LOG_FUNCTION (this); |
| 794 |
| 795 // setup the UE side of SRB0 |
| 796 uint8_t lcid = 0; |
| 797 |
| 798 Ptr<NistLteRlc> rlc = CreateObject<NistLteRlcTm> ()->GetObject<NistLteRlc> (); |
| 799 rlc->SetNistLteMacSapProvider (m_macSapProvider); |
| 800 rlc->SetRnti (m_rnti); |
| 801 rlc->SetLcId (lcid); |
| 802 |
| 803 m_srb0 = CreateObject<LteSignalingRadioNistBearerInfo> (); |
| 804 m_srb0->m_rlc = rlc; |
| 805 m_srb0->m_srbIdentity = 0; |
| 806 NistLteUeRrcSapUser::NistSetupParameters ueParams; |
| 807 ueParams.srb0SapProvider = m_srb0->m_rlc->GetNistLteRlcSapProvider (); |
| 808 ueParams.srb1SapProvider = 0; |
| 809 m_rrcSapUser->Setup (ueParams); |
| 810 |
| 811 // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration: |
| 812 NistLteUeCmacSapProvider::NistLogicalChannelConfig lcConfig; |
| 813 lcConfig.priority = 0; // highest priority |
| 814 lcConfig.prioritizedBitRateKbps = 65535; // maximum |
| 815 lcConfig.bucketSizeDurationMs = 65535; // maximum |
| 816 lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0 |
| 817 |
| 818 m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetNistLteMacSapUser ()); |
| 819 |
| 820 } |
| 821 |
| 822 |
| 823 void |
| 824 NistLteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid) |
| 825 { |
| 826 NS_LOG_FUNCTION (this << packet); |
| 827 |
| 828 uint8_t drbid = Bid2Drbid (bid); |
| 829 |
| 830 if (drbid != 0) |
| 831 { |
| 832 std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.
find (drbid); |
| 833 NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " <
< drbid); |
| 834 |
| 835 NistLtePdcpSapProvider::NistTransmitPdcpSduParameters params; |
| 836 params.pdcpSdu = packet; |
| 837 params.rnti = m_rnti; |
| 838 params.lcid = it->second->m_logicalChannelIdentity; |
| 839 |
| 840 NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending packet " << packet |
| 841 << " on DRBID " << (uint32_t) drbid |
| 842 << " (LCID " << (uint32_t) params.lcid << ")" |
| 843 << " (" << packet->GetSize () << " bytes)"); |
| 844 it->second->m_pdcp->GetNistLtePdcpSapProvider ()->TransmitPdcpSdu (params); |
| 845 } |
| 846 } |
| 847 |
| 848 void |
| 849 NistLteUeRrc::DoSendData (Ptr<Packet> packet, uint32_t group) |
| 850 { |
| 851 NS_LOG_FUNCTION (this << packet << "for sidelink group " <<group); |
| 852 //Find the PDCP for sidelink transmission |
| 853 Ptr<LteSidelinkRadioBearerInfo> slrb = m_sidelinkConfiguration->GetSidelinkRad
ioBearer (group); |
| 854 NS_ASSERT_MSG (slrb, "could not find sidelink bearer for group == " << group);
//the NAS should be aware about the existance of the bearer or not |
| 855 |
| 856 NistLtePdcpSapProvider::NistTransmitPdcpSduParameters params; |
| 857 params.pdcpSdu = packet; |
| 858 params.rnti = m_rnti; |
| 859 params.lcid = slrb->m_logicalChannelIdentity; |
| 860 |
| 861 NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending packet " << packet |
| 862 << " on SLRBBID " << (uint32_t) group |
| 863 << " (LCID " << (uint32_t) params.lcid << ")" |
| 864 << " (" << packet->GetSize () << " bytes)"); |
| 865 slrb->m_pdcp->GetNistLtePdcpSapProvider ()->TransmitPdcpSdu (params); |
| 866 } |
| 867 |
| 868 void |
| 869 NistLteUeRrc::DoDisconnect () |
| 870 { |
| 871 NS_LOG_FUNCTION (this); |
| 872 |
| 873 switch (m_state) |
| 874 { |
| 875 case IDLE_START: |
| 876 case IDLE_CELL_SEARCH: |
| 877 case IDLE_WAIT_MIB_SIB1: |
| 878 case IDLE_WAIT_MIB: |
| 879 case IDLE_WAIT_SIB1: |
| 880 case IDLE_CAMPED_NORMALLY: |
| 881 NS_LOG_INFO ("already disconnected"); |
| 882 break; |
| 883 |
| 884 case IDLE_WAIT_SIB2: |
| 885 case IDLE_CONNECTING: |
| 886 NS_FATAL_ERROR ("cannot abort connection setup procedure"); |
| 887 break; |
| 888 |
| 889 case CONNECTED_NORMALLY: |
| 890 case CONNECTED_HANDOVER: |
| 891 case CONNECTED_PHY_PROBLEM: |
| 892 case CONNECTED_REESTABLISHING: |
| 893 LeaveConnectedMode (); |
| 894 break; |
| 895 |
| 896 default: // i.e. IDLE_RANDOM_ACCESS |
| 897 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 898 break; |
| 899 } |
| 900 } |
| 901 |
| 902 void |
| 903 NistLteUeRrc::DoActivateSidelinkRadioBearer (uint32_t group, bool tx, bool rx) |
| 904 { |
| 905 NS_LOG_FUNCTION (this); |
| 906 |
| 907 NS_ASSERT (m_sidelinkConfiguration->GetSidelinkRadioBearer (m_sidelinkConfigur
ation->m_sourceL2Id, group) == NULL); |
| 908 ·· |
| 909 switch (m_state) |
| 910 { |
| 911 case IDLE_START: |
| 912 case IDLE_CELL_SEARCH: |
| 913 case IDLE_WAIT_MIB_SIB1: |
| 914 case IDLE_WAIT_MIB: |
| 915 case IDLE_WAIT_SIB1: |
| 916 case IDLE_CAMPED_NORMALLY: |
| 917 NS_LOG_INFO ("Considering out of network"); |
| 918 std::cout << "IMSI " << m_imsi << " considered out of network" << std::end
l; |
| 919 |
| 920 if (m_rnti == 0) |
| 921 { |
| 922 //the RNTI was not configured, this is the first call to sidelink conf
iguration |
| 923 NS_LOG_INFO (this << " Setting RNTI to " << (uint16_t) (m_imsi & 0xFF
FF)); |
| 924 //preconfigure the RNTI to the IMSI's 16 LSB for uniqueness |
| 925 DoSetTemporaryCellRnti ( (uint16_t) (m_imsi & 0xFFFF)); |
| 926 //propagate to the MAC (normally the MAC indicates the RNTI when recei
ving message from the eNodeB) |
| 927 m_cmacSapProvider->SetRnti (m_rnti); |
| 928 //since it is first time, configure the physical layer as well |
| 929 m_cphySapProvider->ConfigureUplink (m_sidelinkConfiguration->GetSlPrec
onfiguration().preconfigGeneral.carrierFreq, m_sidelinkConfiguration->GetSlPreco
nfiguration().preconfigGeneral.slBandwidth); |
| 930 } |
| 931 |
| 932 if (tx) |
| 933 { |
| 934 Ptr<LteSidelinkRadioBearerInfo> slbInfo = AddSlrb (m_sidelinkConfigura
tion->m_sourceL2Id, group, m_sidelinkConfiguration->GetNextLcid ()); |
| 935 NS_LOG_INFO ("Created new TX SLRB for group " << group << " LCID=" <<
(slbInfo->m_logicalChannelIdentity & 0xF)); |
| 936 } |
| 937 if (rx) |
| 938 { |
| 939 //Add to the list of group to monitor for sidelink |
| 940 m_sidelinkConfiguration->m_rxGroup.push_back (group); |
| 941 //tell the phy to listen for the group |
| 942 m_cphySapProvider->AddSlDestination (group); |
| 943 m_cmacSapProvider->AddSlDestination (group); |
| 944 } |
| 945 ······ |
| 946 NS_ASSERT (m_sidelinkConfiguration->GetSlPreconfiguration().preconfigComm.
nbPools >0); |
| 947 //Activate bearer using preconfiguration if available |
| 948 if (tx) { |
| 949 NS_LOG_INFO ("Configuring Tx pool"); |
| 950 Ptr<SidelinkTxCommResourcePool> txPool = CreateObject<SidelinkTxCommReso
urcePool>(); |
| 951 txPool->SetPool (m_sidelinkConfiguration->GetSlPreconfiguration().precon
figComm.pools[0]); |
| 952 std::list <uint32_t>::iterator it; |
| 953 std::list <uint32_t> destinations = m_sidelinkConfiguration->GetTxDestin
ations (); |
| 954 //int index = 0; |
| 955 //currently we can only use one pool so all groups will use the same one |
| 956 ········ |
| 957 //for (it = destinations.begin() ; it != destinations.end() ; it++) { |
| 958 //m_cmacSapProvider->AddSlTxPool (*it, txPool); |
| 959 //} |
| 960 m_cmacSapProvider->AddSlTxPool (group, txPool); |
| 961 //if this is the first group setup, register pool with physical layer, o
therwise it has already been done |
| 962 if (destinations.size() == 1)· |
| 963 { |
| 964 //inform PHY about pool |
| 965 m_cphySapProvider->SetSlTxPool (txPool);············ |
| 966 } |
| 967 } |
| 968 if (tx || rx) |
| 969 { |
| 970 //Configure receiving pool |
| 971 std::list< Ptr<SidelinkRxCommResourcePool> > pools; |
| 972 Ptr<SidelinkRxCommResourcePool> pool = CreateObject <SidelinkRxCommRes
ourcePool> (); |
| 973 pool->SetPool (m_sidelinkConfiguration->GetSlPreconfiguration().precon
figComm.pools[0]); |
| 974 //must find ways to store Rx pool though it is in different format |
| 975 //m_sidelinkConfiguration->rxPools.push_back (std::make_pair(msg.sib18
.commConfig.commRxPool.pools[i], pool)); |
| 976 pools.push_back (pool); |
| 977 m_cmacSapProvider->SetSlRxPools (pools); |
| 978 m_cphySapProvider->SetSlRxPools (pools); |
| 979 } |
| 980 //for testing, just indicate it is ok |
| 981 m_asSapUser->NotifySidelinkRadioBearerActivated (group); |
| 982 break; |
| 983 ······ |
| 984 case IDLE_WAIT_SIB2: |
| 985 case IDLE_CONNECTING: |
| 986 NS_LOG_INFO ("Connecting, must wait to send message"); |
| 987 break; |
| 988 ······ |
| 989 case CONNECTED_NORMALLY: |
| 990 case CONNECTED_HANDOVER: |
| 991 case CONNECTED_PHY_PROBLEM: |
| 992 case CONNECTED_REESTABLISHING: |
| 993 NS_LOG_INFO ("Considering in coverage"); |
| 994 if (tx) |
| 995 { |
| 996 Ptr<LteSidelinkRadioBearerInfo> slbInfo = AddSlrb (m_sidelinkConfigura
tion->m_sourceL2Id, group, m_sidelinkConfiguration->GetNextLcid ()); |
| 997 NS_LOG_INFO ("Created new TX SLRB for group " << group << " LCID=" <<
(slbInfo->m_logicalChannelIdentity & 0xF)); |
| 998 } |
| 999 if (rx) |
| 1000 { |
| 1001 //Add to the list of group to monitor for sidelink |
| 1002 m_sidelinkConfiguration->m_rxGroup.push_back (group); |
| 1003 //tell the phy to listen for the group |
| 1004 m_cphySapProvider->AddSlDestination (group); |
| 1005 m_cmacSapProvider->AddSlDestination (group); |
| 1006 } |
| 1007 //Try to send to eNodeB |
| 1008 SendSidelinkUeInformation (); |
| 1009 break; |
| 1010 ········ |
| 1011 default: // i.e. IDLE_RANDOM_ACCESS |
| 1012 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1013 break; |
| 1014 } |
| 1015 ·· |
| 1016 } |
| 1017 |
| 1018 void |
| 1019 NistLteUeRrc::DoDeactivateSidelinkRadioBearer (uint32_t group) |
| 1020 { |
| 1021 NS_LOG_FUNCTION (this); |
| 1022 |
| 1023 //TODO: need handling of SLRBs for the group coming from other UEs as well. |
| 1024 ·· |
| 1025 if (m_sidelinkConfiguration->DeleteSidelinkRadioBearer (m_sidelinkConfiguratio
n->m_sourceL2Id, group)) |
| 1026 { |
| 1027 switch (m_state) |
| 1028 { |
| 1029 case IDLE_START: |
| 1030 case IDLE_CELL_SEARCH: |
| 1031 case IDLE_WAIT_MIB_SIB1: |
| 1032 case IDLE_WAIT_MIB: |
| 1033 case IDLE_WAIT_SIB1: |
| 1034 case IDLE_CAMPED_NORMALLY: |
| 1035 NS_LOG_INFO ("Considering out of network"); |
| 1036 //Activate bearer using preconfiguration if available |
| 1037 //TBD········ |
| 1038 break;················ |
| 1039 case CONNECTED_NORMALLY: |
| 1040 case CONNECTED_HANDOVER: |
| 1041 case CONNECTED_PHY_PROBLEM: |
| 1042 case CONNECTED_REESTABLISHING: |
| 1043 NS_LOG_INFO ("Considering in coverage"); |
| 1044 //Try to send to eNodeB |
| 1045 SendSidelinkUeInformation (); |
| 1046 break; |
| 1047 ········ |
| 1048 default: // i.e. IDLE_RANDOM_ACCESS |
| 1049 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1050 break; |
| 1051 } |
| 1052 } |
| 1053 ·· |
| 1054 } |
| 1055 |
| 1056 Ptr<LteSidelinkRadioBearerInfo> |
| 1057 NistLteUeRrc::AddSlrb (uint32_t source, uint32_t destination, uint8_t lcid) |
| 1058 { |
| 1059 Ptr<LteSidelinkRadioBearerInfo> slbInfo = CreateObject <LteSidelinkRadioBearer
Info> (); |
| 1060 slbInfo->m_sourceL2Id = source; |
| 1061 slbInfo->m_destinationL2Id = destination; |
| 1062 slbInfo->m_logicalChannelIdentity = lcid; |
| 1063 //slbInfo->m_tx = tx; |
| 1064 //slbInfo->m_rx = rx; |
| 1065 m_sidelinkConfiguration->AddSidelinkRadioBearer (slbInfo); |
| 1066 |
| 1067 //create PDCP/RLC stack |
| 1068 ObjectFactory rlcObjectFactory; |
| 1069 rlcObjectFactory.SetTypeId (NistLteRlcUm::GetTypeId ()); |
| 1070 Ptr<NistLteRlc> rlc = rlcObjectFactory.Create ()->GetObject<NistLteRlc> (); |
| 1071 rlc->SetNistLteMacSapProvider (m_macSapProvider); |
| 1072 rlc->SetRnti (m_rnti); //?? |
| 1073 rlc->SetLcId (slbInfo->m_logicalChannelIdentity); |
| 1074 rlc->SetSourceL2Id (slbInfo->m_sourceL2Id); |
| 1075 rlc->SetDestinationL2Id (slbInfo->m_destinationL2Id); |
| 1076 ···· |
| 1077 slbInfo->m_rlc = rlc; |
| 1078 ········ |
| 1079 Ptr<NistLtePdcp> pdcp = CreateObject<NistLtePdcp> (); |
| 1080 pdcp->SetRnti (m_rnti); |
| 1081 pdcp->SetLcId (slbInfo->m_logicalChannelIdentity); |
| 1082 pdcp->SetSourceL2Id (slbInfo->m_sourceL2Id); |
| 1083 pdcp->SetDestinationL2Id (slbInfo->m_destinationL2Id); |
| 1084 pdcp->SetNistLtePdcpSapUser (m_drbPdcpSapUser); |
| 1085 pdcp->SetNistLteRlcSapProvider (rlc->GetNistLteRlcSapProvider ()); |
| 1086 rlc->SetNistLteRlcSapUser (pdcp->GetNistLteRlcSapUser ()); |
| 1087 slbInfo->m_pdcp = pdcp; |
| 1088 |
| 1089 |
| 1090 struct NistLteUeCmacSapProvider::NistLogicalChannelConfig lcConfig; |
| 1091 lcConfig.priority = 9; |
| 1092 lcConfig.prioritizedBitRateKbps = 65535; |
| 1093 lcConfig.bucketSizeDurationMs = 65535; |
| 1094 lcConfig.logicalChannelGroup = 3; //"11" as per 36.321······ |
| 1095 |
| 1096 m_cmacSapProvider->AddLc (slbInfo->m_logicalChannelIdentity, |
| 1097 slbInfo->m_sourceL2Id, |
| 1098 slbInfo->m_destinationL2Id, |
| 1099 lcConfig, |
| 1100 rlc->GetNistLteMacSapUser ()); |
| 1101 //rlc->Initialize (); |
| 1102 |
| 1103 return slbInfo; |
| 1104 } |
| 1105 |
| 1106 void |
| 1107 NistLteUeRrc::DoAddDiscoveryApps (std::list<uint32_t> apps, bool rxtx) |
| 1108 { |
| 1109 NS_LOG_FUNCTION (this); |
| 1110 ·· |
| 1111 switch (m_state) |
| 1112 { |
| 1113 case IDLE_START: |
| 1114 case IDLE_CELL_SEARCH: |
| 1115 case IDLE_WAIT_MIB_SIB1: |
| 1116 case IDLE_WAIT_MIB: |
| 1117 case IDLE_WAIT_SIB1: |
| 1118 case IDLE_CAMPED_NORMALLY: |
| 1119 NS_LOG_INFO ("Considering out of network"); |
| 1120 |
| 1121 if (m_rnti == 0) |
| 1122 { |
| 1123 NS_LOG_INFO (this << " Setting RNTI to " << (uint16_t) (m_imsi & 0xFF
FF)); |
| 1124 //preconfigure the RNTI to the IMSI's 16 LSB for uniqueness |
| 1125 DoSetTemporaryCellRnti ( (uint16_t) (m_imsi & 0xFFFF)); |
| 1126 //propagate to the MAC (normally the MAC indicates the RNTI when recei
ving message from the eNodeB) |
| 1127 m_cmacSapProvider->SetRnti (m_rnti); |
| 1128 //since it is first time, configure the physical layer as well |
| 1129 m_cphySapProvider->ConfigureUplink (m_sidelinkConfiguration->GetSlPrec
onfiguration().preconfigGeneral.carrierFreq, m_sidelinkConfiguration->GetSlPreco
nfiguration().preconfigGeneral.slBandwidth); |
| 1130 } |
| 1131 ·········· |
| 1132 m_sidelinkConfiguration->AddDiscoveryApps (apps, rxtx); |
| 1133 NS_LOG_INFO ("Created new discovery Applications for UE " << m_rnti ); |
| 1134 //Inform MAC about new disc apps |
| 1135 m_cmacSapProvider->ModifyDiscTxApps (m_sidelinkConfiguration->m_announceAp
ps); |
| 1136 m_cmacSapProvider->ModifyDiscRxApps (m_sidelinkConfiguration->m_monitorApp
s); |
| 1137 |
| 1138 //Set pool using preconfigured one if it exits |
| 1139 if (m_sidelinkConfiguration->GetSlPreconfiguration().preconfigDisc.nbPools
>0) |
| 1140 { |
| 1141 //announce: Tx |
| 1142 if (rxtx) |
| 1143 { |
| 1144 NS_LOG_INFO ("Configuring Tx preconfigured pool"); |
| 1145 Ptr<SidelinkTxDiscResourcePool> txPool = CreateObject<SidelinkTxDiscRe
sourcePool>(); |
| 1146 txPool->SetPool (m_sidelinkConfiguration->GetSlPreconfiguration().prec
onfigDisc.pools[0]); |
| 1147 //inform MAC and PHY about the pool |
| 1148 m_cmacSapProvider->AddSlTxPool (txPool); |
| 1149 m_cphySapProvider->SetSlTxPool (txPool); |
| 1150 } |
| 1151 //monitor: Rx |
| 1152 else· |
| 1153 { |
| 1154 std::list< Ptr<SidelinkRxDiscResourcePool> > pools; |
| 1155 Ptr<SidelinkRxDiscResourcePool> pool = CreateObject <SidelinkRxDiscRes
ourcePool> (); |
| 1156 pool->SetPool (m_sidelinkConfiguration->GetSlPreconfiguration().precon
figDisc.pools[0]); |
| 1157 pools.push_back (pool);············ |
| 1158 m_cmacSapProvider->SetSlRxPools (pools); |
| 1159 m_cphySapProvider->SetSlRxPools (pools); |
| 1160 } |
| 1161 } |
| 1162 |
| 1163 break; |
| 1164 ······ |
| 1165 case IDLE_WAIT_SIB2: |
| 1166 case IDLE_CONNECTING: |
| 1167 NS_LOG_INFO ("Connecting, must wait to send message"); |
| 1168 break; |
| 1169 ······ |
| 1170 case CONNECTED_NORMALLY: |
| 1171 case CONNECTED_HANDOVER: |
| 1172 case CONNECTED_PHY_PROBLEM: |
| 1173 case CONNECTED_REESTABLISHING: |
| 1174 NS_LOG_INFO ("Considering in coverage"); |
| 1175 m_sidelinkConfiguration->AddDiscoveryApps (apps, rxtx); |
| 1176 NS_LOG_INFO ("Created new discovery Applications for UE " << m_rnti ); |
| 1177 //Inform MAC about new disc apps |
| 1178 m_cmacSapProvider->ModifyDiscTxApps (m_sidelinkConfiguration->m_announceAp
ps); |
| 1179 m_cmacSapProvider->ModifyDiscRxApps (m_sidelinkConfiguration->m_monitorApp
s); |
| 1180 //Try to send to eNodeB |
| 1181 SendSidelinkUeInformation (); |
| 1182 break; |
| 1183 ········ |
| 1184 default: // i.e. IDLE_RANDOM_ACCESS |
| 1185 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1186 break; |
| 1187 } |
| 1188 ·· |
| 1189 } |
| 1190 |
| 1191 void |
| 1192 NistLteUeRrc::DoRemoveDiscoveryApps (std::list<uint32_t> apps, bool rxtx) |
| 1193 { |
| 1194 NS_LOG_FUNCTION (this); |
| 1195 |
| 1196 m_sidelinkConfiguration->RemoveDiscoveryApps (apps, rxtx); |
| 1197 NS_LOG_INFO ("deleting new discovery Applications for UE " << m_rnti ); |
| 1198 // Inform MAC |
| 1199 m_cmacSapProvider->ModifyDiscTxApps (m_sidelinkConfiguration->m_announceApps); |
| 1200 m_cmacSapProvider->ModifyDiscRxApps (m_sidelinkConfiguration->m_monitorApps); |
| 1201 |
| 1202 switch (m_state) |
| 1203 { |
| 1204 case IDLE_START: |
| 1205 case IDLE_CELL_SEARCH: |
| 1206 case IDLE_WAIT_MIB_SIB1: |
| 1207 case IDLE_WAIT_MIB: |
| 1208 case IDLE_WAIT_SIB1: |
| 1209 case IDLE_CAMPED_NORMALLY: |
| 1210 NS_LOG_INFO ("Considering out of network"); |
| 1211 //Activate bearer using preconfiguration if available |
| 1212 //TBD···· |
| 1213 break;················ |
| 1214 case CONNECTED_NORMALLY: |
| 1215 case CONNECTED_HANDOVER: |
| 1216 case CONNECTED_PHY_PROBLEM: |
| 1217 case CONNECTED_REESTABLISHING: |
| 1218 NS_LOG_INFO ("Considering in coverage"); |
| 1219 //Try to send to eNodeB |
| 1220 SendSidelinkUeInformation (); |
| 1221 break; |
| 1222 ········ |
| 1223 default: // i.e. IDLE_RANDOM_ACCESS |
| 1224 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1225 break; |
| 1226 } |
| 1227 |
| 1228 ·· |
| 1229 }·· |
| 1230 |
| 1231 void |
| 1232 NistLteUeRrc::DoReceivePdcpSdu (NistLtePdcpSapUser::NistReceivePdcpSduParameters
params) |
| 1233 { |
| 1234 NS_LOG_FUNCTION (this); |
| 1235 m_asSapUser->RecvData (params.pdcpSdu); |
| 1236 } |
| 1237 |
| 1238 |
| 1239 void |
| 1240 NistLteUeRrc::DoSetTemporaryCellRnti (uint16_t rnti) |
| 1241 { |
| 1242 NS_LOG_FUNCTION (this << rnti); |
| 1243 m_rnti = rnti; |
| 1244 m_srb0->m_rlc->SetRnti (m_rnti); |
| 1245 m_cphySapProvider->SetRnti (m_rnti); |
| 1246 } |
| 1247 |
| 1248 void |
| 1249 NistLteUeRrc::DoNotifyRandomAccessSuccessful () |
| 1250 { |
| 1251 NS_LOG_FUNCTION (this << m_imsi << ToString (m_state)); |
| 1252 m_randomAccessSuccessfulTrace (m_imsi, m_cellId, m_rnti); |
| 1253 |
| 1254 switch (m_state) |
| 1255 { |
| 1256 case IDLE_RANDOM_ACCESS: |
| 1257 { |
| 1258 // we just received a RAR with a T-C-RNTI and an UL grant |
| 1259 // send RRC connection request as message 3 of the random access procedu
re· |
| 1260 SwitchToState (IDLE_CONNECTING); |
| 1261 NistLteRrcSap::NistRrcConnectionRequest msg; |
| 1262 msg.ueIdentity = m_imsi; |
| 1263 m_rrcSapUser->SendNistRrcConnectionRequest (msg);· |
| 1264 m_connectionTimeout = Simulator::Schedule (m_t300, |
| 1265 &NistLteUeRrc::ConnectionTime
out, |
| 1266 this); |
| 1267 } |
| 1268 break; |
| 1269 |
| 1270 case CONNECTED_HANDOVER: |
| 1271 { |
| 1272 NistLteRrcSap::NistRrcConnectionReconfigurationCompleted msg; |
| 1273 msg.rrcTransactionIdentifier = m_lastRrcTransactionIdentifier; |
| 1274 m_rrcSapUser->SendNistRrcConnectionReconfigurationCompleted (msg); |
| 1275 |
| 1276 // 3GPP TS 36.331 section 5.5.6.1 Measurements related actions upon hand
over |
| 1277 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measIdIt; |
| 1278 for (measIdIt = m_varNistMeasConfig.measIdList.begin (); |
| 1279 measIdIt != m_varNistMeasConfig.measIdList.end (); |
| 1280 ++measIdIt) |
| 1281 { |
| 1282 NistVarMeasReportListClear (measIdIt->second.measId); |
| 1283 } |
| 1284 //if target cell sending SIB 18 or 19 and SidelinkUEInformation was sent
in the last second |
| 1285 //with interest/resource request, |
| 1286 //initiate transmission of the SidelinkUEInformation message in accordan
ce with 5.X.2.3 |
| 1287 if ((m_sidelinkConfiguration->IsCellBroadcastingSIB18 (m_cellId) || m_si
delinkConfiguration->IsCellBroadcastingSIB19 (m_cellId)) && m_sidelinkConfigurat
ion->GetTimeSinceLastTransmissionOfSidelinkUeInformation () < 1.0) { |
| 1288 SendSidelinkUeInformation (); |
| 1289 } |
| 1290 ········ |
| 1291 SwitchToState (CONNECTED_NORMALLY); |
| 1292 m_handoverEndOkTrace (m_imsi, m_cellId, m_rnti); |
| 1293 } |
| 1294 break; |
| 1295 |
| 1296 default: |
| 1297 NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state)); |
| 1298 break;· |
| 1299 } |
| 1300 } |
| 1301 |
| 1302 void |
| 1303 NistLteUeRrc::DoNotifyRandomAccessFailed () |
| 1304 { |
| 1305 NS_LOG_FUNCTION (this << m_imsi << ToString (m_state)); |
| 1306 m_randomAccessErrorTrace (m_imsi, m_cellId, m_rnti); |
| 1307 |
| 1308 switch (m_state) |
| 1309 { |
| 1310 case IDLE_RANDOM_ACCESS: |
| 1311 { |
| 1312 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 1313 m_asSapUser->NotifyConnectionFailed (); |
| 1314 } |
| 1315 break; |
| 1316 |
| 1317 case CONNECTED_HANDOVER: |
| 1318 { |
| 1319 m_handoverEndErrorTrace (m_imsi, m_cellId, m_rnti); |
| 1320 /** |
| 1321 * \todo After a handover failure because of a random access failure, |
| 1322 * send an RRC Connection Re-establishment and switch to |
| 1323 * CONNECTED_REESTABLISHING state. |
| 1324 */ |
| 1325 } |
| 1326 break; |
| 1327 |
| 1328 default: |
| 1329 NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state)); |
| 1330 break; |
| 1331 } |
| 1332 } |
| 1333 |
| 1334 |
| 1335 void |
| 1336 NistLteUeRrc::DoSetCsgWhiteList (uint32_t csgId) |
| 1337 { |
| 1338 NS_LOG_FUNCTION (this << m_imsi << csgId); |
| 1339 m_csgWhiteList = csgId; |
| 1340 } |
| 1341 |
| 1342 void· |
| 1343 NistLteUeRrc::DoStartCellSelection (uint16_t dlEarfcn) |
| 1344 { |
| 1345 NS_LOG_FUNCTION (this << m_imsi << dlEarfcn); |
| 1346 NS_ASSERT_MSG (m_state == IDLE_START, |
| 1347 "cannot start cell selection from state " << ToString (m_state)
); |
| 1348 m_dlEarfcn = dlEarfcn; |
| 1349 m_cphySapProvider->StartCellSearch (dlEarfcn); |
| 1350 SwitchToState (IDLE_CELL_SEARCH); |
| 1351 } |
| 1352 |
| 1353 void· |
| 1354 NistLteUeRrc::DoForceCampedOnEnb (uint16_t cellId, uint16_t dlEarfcn) |
| 1355 { |
| 1356 NS_LOG_FUNCTION (this << m_imsi << cellId << dlEarfcn); |
| 1357 |
| 1358 switch (m_state) |
| 1359 { |
| 1360 case IDLE_START: |
| 1361 m_cellId = cellId; |
| 1362 m_dlEarfcn = dlEarfcn; |
| 1363 m_cphySapProvider->SynchronizeWithEnb (m_cellId, m_dlEarfcn); |
| 1364 SwitchToState (IDLE_WAIT_MIB); |
| 1365 break; |
| 1366 |
| 1367 case IDLE_CELL_SEARCH: |
| 1368 case IDLE_WAIT_MIB_SIB1: |
| 1369 case IDLE_WAIT_SIB1: |
| 1370 NS_FATAL_ERROR ("cannot abort cell selection " << ToString (m_state)); |
| 1371 break; |
| 1372 |
| 1373 case IDLE_WAIT_MIB: |
| 1374 NS_LOG_INFO ("already forced to camp to cell " << m_cellId); |
| 1375 break; |
| 1376 |
| 1377 case IDLE_CAMPED_NORMALLY: |
| 1378 case IDLE_WAIT_SIB2: |
| 1379 case IDLE_RANDOM_ACCESS: |
| 1380 case IDLE_CONNECTING: |
| 1381 NS_LOG_INFO ("already camped to cell " << m_cellId); |
| 1382 break; |
| 1383 |
| 1384 case CONNECTED_NORMALLY: |
| 1385 case CONNECTED_HANDOVER: |
| 1386 case CONNECTED_PHY_PROBLEM: |
| 1387 case CONNECTED_REESTABLISHING: |
| 1388 NS_LOG_INFO ("already connected to cell " << m_cellId); |
| 1389 break; |
| 1390 |
| 1391 default: |
| 1392 NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state)); |
| 1393 break; |
| 1394 } |
| 1395 |
| 1396 } |
| 1397 |
| 1398 void |
| 1399 NistLteUeRrc::DoConnect () |
| 1400 { |
| 1401 NS_LOG_FUNCTION (this << m_imsi); |
| 1402 |
| 1403 switch (m_state) |
| 1404 { |
| 1405 case IDLE_START: |
| 1406 case IDLE_CELL_SEARCH: |
| 1407 case IDLE_WAIT_MIB_SIB1: |
| 1408 case IDLE_WAIT_SIB1: |
| 1409 case IDLE_WAIT_MIB: |
| 1410 m_connectionPending = true; |
| 1411 break; |
| 1412 |
| 1413 case IDLE_CAMPED_NORMALLY: |
| 1414 m_connectionPending = true; |
| 1415 SwitchToState (IDLE_WAIT_SIB2); |
| 1416 break; |
| 1417 |
| 1418 case IDLE_WAIT_SIB2: |
| 1419 case IDLE_RANDOM_ACCESS: |
| 1420 case IDLE_CONNECTING: |
| 1421 NS_LOG_INFO ("already connecting"); |
| 1422 break; |
| 1423 |
| 1424 case CONNECTED_NORMALLY: |
| 1425 case CONNECTED_REESTABLISHING: |
| 1426 case CONNECTED_HANDOVER: |
| 1427 NS_LOG_INFO ("already connected"); |
| 1428 break; |
| 1429 |
| 1430 default: |
| 1431 NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state)); |
| 1432 break; |
| 1433 } |
| 1434 } |
| 1435 |
| 1436 |
| 1437 |
| 1438 // CPHY SAP methods |
| 1439 |
| 1440 void |
| 1441 NistLteUeRrc::DoRecvNistMasterInformationBlock (uint16_t cellId, |
| 1442 NistLteRrcSap::NistMasterInformationBloc
k msg) |
| 1443 {· |
| 1444 m_dlBandwidth = msg.dlBandwidth; |
| 1445 m_cphySapProvider->SetDlBandwidth (msg.dlBandwidth); |
| 1446 m_hasReceivedMib = true; |
| 1447 m_mibReceivedTrace (m_imsi, m_cellId, m_rnti, cellId); |
| 1448 |
| 1449 switch (m_state) |
| 1450 { |
| 1451 case IDLE_WAIT_MIB: |
| 1452 // manual attachment |
| 1453 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 1454 break; |
| 1455 |
| 1456 case IDLE_WAIT_MIB_SIB1: |
| 1457 // automatic attachment from Idle mode cell selection |
| 1458 SwitchToState (IDLE_WAIT_SIB1); |
| 1459 break; |
| 1460 |
| 1461 default: |
| 1462 // do nothing extra |
| 1463 break; |
| 1464 } |
| 1465 } |
| 1466 |
| 1467 void |
| 1468 NistLteUeRrc::DoRecvNistSystemInformationBlockType1 (uint16_t cellId, |
| 1469 NistLteRrcSap::NistSystemInformatio
nBlockType1 msg) |
| 1470 { |
| 1471 switch (m_state) |
| 1472 { |
| 1473 case IDLE_WAIT_SIB1: |
| 1474 NS_ASSERT_MSG (cellId == msg.cellAccessRelatedInfo.cellIdentity, |
| 1475 "Cell identity in SIB1 does not match with the originating
cell"); |
| 1476 m_hasReceivedSib1 = true; |
| 1477 m_lastSib1 = msg; |
| 1478 m_sib1ReceivedTrace (m_imsi, m_cellId, m_rnti, cellId); |
| 1479 EvaluateCellForSelection (); |
| 1480 break; |
| 1481 |
| 1482 case IDLE_CAMPED_NORMALLY: |
| 1483 case IDLE_RANDOM_ACCESS: |
| 1484 case IDLE_CONNECTING: |
| 1485 case CONNECTED_NORMALLY: |
| 1486 case CONNECTED_HANDOVER: |
| 1487 case CONNECTED_PHY_PROBLEM: |
| 1488 case CONNECTED_REESTABLISHING: |
| 1489 NS_ASSERT_MSG (cellId == msg.cellAccessRelatedInfo.cellIdentity, |
| 1490 "Cell identity in SIB1 does not match with the originating
cell"); |
| 1491 m_hasReceivedSib1 = true; |
| 1492 m_lastSib1 = msg; |
| 1493 m_sib1ReceivedTrace (m_imsi, m_cellId, m_rnti, cellId); |
| 1494 break; |
| 1495 |
| 1496 case IDLE_WAIT_MIB_SIB1: |
| 1497 // MIB has not been received, so ignore this SIB1 |
| 1498 break; |
| 1499 |
| 1500 default: // e.g. IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_SIB2 |
| 1501 // do nothing |
| 1502 break; |
| 1503 } |
| 1504 } |
| 1505 |
| 1506 void |
| 1507 NistLteUeRrc::DoReportNistUeMeasurements (NistLteUeCphySapUser::NistUeMeasuremen
tsParameters params) |
| 1508 { |
| 1509 NS_LOG_FUNCTION (this); |
| 1510 |
| 1511 // layer 3 filtering does not apply in IDLE mode |
| 1512 bool useLayer3Filtering = (m_state == CONNECTED_NORMALLY); |
| 1513 |
| 1514 std::vector <NistLteUeCphySapUser::NistUeMeasurementsElement>::iterator newMea
sIt; |
| 1515 for (newMeasIt = params.m_ueMeasurementsList.begin (); |
| 1516 newMeasIt != params.m_ueMeasurementsList.end (); ++newMeasIt) |
| 1517 { |
| 1518 SaveNistUeMeasurements (newMeasIt->m_cellId, newMeasIt->m_rsrp, |
| 1519 newMeasIt->m_rsrq, useLayer3Filtering); |
| 1520 } |
| 1521 |
| 1522 if (m_state == IDLE_CELL_SEARCH) |
| 1523 { |
| 1524 // start decoding BCH |
| 1525 SynchronizeToStrongestCell (); |
| 1526 } |
| 1527 else |
| 1528 { |
| 1529 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measIdIt; |
| 1530 for (measIdIt = m_varNistMeasConfig.measIdList.begin (); |
| 1531 measIdIt != m_varNistMeasConfig.measIdList.end (); ++measIdIt) |
| 1532 { |
| 1533 NistMeasurementReportTriggering (measIdIt->first); |
| 1534 } |
| 1535 } |
| 1536 |
| 1537 } // end of NistLteUeRrc::DoReportNistUeMeasurements |
| 1538 |
| 1539 |
| 1540 |
| 1541 // RRC SAP methods |
| 1542 |
| 1543 void· |
| 1544 NistLteUeRrc::DoCompleteSetup (NistLteUeRrcSapProvider::CompleteNistSetupParamet
ers params) |
| 1545 { |
| 1546 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1547 m_srb0->m_rlc->SetNistLteRlcSapUser (params.srb0SapUser); |
| 1548 if (m_srb1) |
| 1549 { |
| 1550 m_srb1->m_pdcp->SetNistLtePdcpSapUser (params.srb1SapUser); |
| 1551 } |
| 1552 } |
| 1553 |
| 1554 |
| 1555 void· |
| 1556 NistLteUeRrc::DoRecvNistSystemInformation (NistLteRrcSap::NistSystemInformation
msg) |
| 1557 { |
| 1558 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1559 |
| 1560 if (msg.haveSib2) |
| 1561 { |
| 1562 switch (m_state) |
| 1563 { |
| 1564 case IDLE_CAMPED_NORMALLY: |
| 1565 case IDLE_WAIT_SIB2: |
| 1566 case IDLE_RANDOM_ACCESS: |
| 1567 case IDLE_CONNECTING: |
| 1568 case CONNECTED_NORMALLY: |
| 1569 case CONNECTED_HANDOVER: |
| 1570 case CONNECTED_PHY_PROBLEM: |
| 1571 case CONNECTED_REESTABLISHING: |
| 1572 m_hasReceivedSib2 = true; |
| 1573 m_ulBandwidth = msg.sib2.freqInfo.ulBandwidth; |
| 1574 m_ulEarfcn = msg.sib2.freqInfo.ulCarrierFreq; |
| 1575 m_sib2ReceivedTrace (m_imsi, m_cellId, m_rnti); |
| 1576 NistLteUeCmacSapProvider::NistRachConfig rc; |
| 1577 rc.numberOfRaPreambles = msg.sib2.radioResourceConfigCommon.rachConfig
Common.preambleInfo.numberOfRaPreambles; |
| 1578 rc.preambleTransMax = msg.sib2.radioResourceConfigCommon.rachConfigCom
mon.raSupervisionInfo.preambleTransMax; |
| 1579 rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfi
gCommon.raSupervisionInfo.raResponseWindowSize; |
| 1580 m_cmacSapProvider->ConfigureRach (rc); |
| 1581 m_cphySapProvider->ConfigureUplink (m_ulEarfcn, m_ulBandwidth); |
| 1582 m_cphySapProvider->ConfigureReferenceSignalPower(msg.sib2.radioResourc
eConfigCommon.pdschConfigCommon.referenceSignalPower); |
| 1583 if (m_state == IDLE_WAIT_SIB2) |
| 1584 { |
| 1585 NS_ASSERT (m_connectionPending); |
| 1586 StartConnection (); |
| 1587 } |
| 1588 break; |
| 1589 |
| 1590 default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_S
IB1, IDLE_WAIT_SIB1 |
| 1591 // do nothing |
| 1592 break; |
| 1593 } |
| 1594 } |
| 1595 if (msg.haveSib18 && m_sidelinkConfiguration != NULL && m_sidelinkConfiguratio
n->IsSlEnabled()) |
| 1596 { |
| 1597 switch (m_state) |
| 1598 { |
| 1599 case IDLE_CAMPED_NORMALLY: |
| 1600 case CONNECTED_NORMALLY: |
| 1601 { |
| 1602 NS_LOG_LOGIC (this << " processing SIB18 in state " << m_state); |
| 1603 //update sidelink information for the cell |
| 1604 std::map <uint16_t, LteUeRrcSl::LteSlCellConfiguration>::iterator it
= m_sidelinkConfiguration->m_slMap.find (m_cellId); |
| 1605 if (it == m_sidelinkConfiguration->m_slMap.end ()) { |
| 1606 NS_LOG_LOGIC (this << " adding SIB18 for cell " << m_cellId); |
| 1607 LteUeRrcSl::LteSlCellConfiguration cellConfig; |
| 1608 cellConfig.cellId = m_cellId; |
| 1609 cellConfig.haveSib18 = true; |
| 1610 cellConfig.sib18 = msg.sib18; |
| 1611 m_sidelinkConfiguration->m_slMap.insert (std::pair<uint16_t, LteUe
RrcSl::LteSlCellConfiguration> (m_cellId, cellConfig)); |
| 1612 } else { |
| 1613 NS_LOG_LOGIC (this << " updating SIB18 for cell " << m_cellId); |
| 1614 it->second.haveSib18 = true; |
| 1615 it->second.sib18 = msg.sib18; |
| 1616 } |
| 1617 if (m_sidelinkConfiguration->IsTxInterested() || m_sidelinkConfigura
tion->IsRxInterested ()) { |
| 1618 //Inform MAC about the pools to be used |
| 1619 //TBD |
| 1620 std::list< Ptr<SidelinkRxCommResourcePool> > pools; |
| 1621 for (int i = 0 ; i < msg.sib18.commConfig.commRxPool.nbPools; i++) |
| 1622 { |
| 1623 Ptr<SidelinkRxCommResourcePool> pool = NULL; |
| 1624 for (uint32_t j = 0 ; j < m_sidelinkConfiguration->rxPools.siz
e() && pool == NULL; j++) |
| 1625 { |
| 1626 ······················ |
| 1627 if (msg.sib18.commConfig.commRxPool.pools[i]== m_sidelinkC
onfiguration->rxPools.at(j).first) |
| 1628 { |
| 1629 pool = m_sidelinkConfiguration->rxPools.at(j).second; |
| 1630 } |
| 1631 } |
| 1632 if (pool == NULL) |
| 1633 { |
| 1634 pool = CreateObject <SidelinkRxCommResourcePool> (); |
| 1635 pool->SetPool (msg.sib18.commConfig.commRxPool.pools[i]); |
| 1636 m_sidelinkConfiguration->rxPools.push_back (std::make_pair
(msg.sib18.commConfig.commRxPool.pools[i], pool)); |
| 1637 } |
| 1638 pools.push_back (pool); |
| 1639 } |
| 1640 m_cmacSapProvider->SetSlRxPools (pools); |
| 1641 m_cphySapProvider->SetSlRxPools (pools); |
| 1642 } |
| 1643 } |
| 1644 break; |
| 1645 default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_S
IB1, IDLE_WAIT_SIB1 |
| 1646 // do nothing |
| 1647 break; |
| 1648 } |
| 1649 |
| 1650 } |
| 1651 |
| 1652 if (msg.haveSib19 && m_sidelinkConfiguration != NULL && m_sidelinkConfigurat
ion->IsDiscEnabled()) |
| 1653 { |
| 1654 switch (m_state) |
| 1655 { |
| 1656 case IDLE_CAMPED_NORMALLY: |
| 1657 case CONNECTED_NORMALLY: |
| 1658 { |
| 1659 NS_LOG_LOGIC (this << " processing SIB19 in state " << m_state); |
| 1660 //update sidelink information for the cell |
| 1661 std::map <uint16_t, LteUeRrcSl::LteSlCellConfiguration>::iterator it =
m_sidelinkConfiguration->m_slMap.find (m_cellId); |
| 1662 if (it == m_sidelinkConfiguration->m_slMap.end ()) { |
| 1663 NS_LOG_LOGIC (this << " adding SIB19 for cell " << m_cellId); |
| 1664 LteUeRrcSl::LteSlCellConfiguration cellConfig; |
| 1665 cellConfig.cellId = m_cellId; |
| 1666 cellConfig.haveSib19 = true; |
| 1667 cellConfig.sib19 = msg.sib19; |
| 1668 m_sidelinkConfiguration->m_slMap.insert (std::pair<uint16_t, LteUeRr
cSl::LteSlCellConfiguration> (m_cellId, cellConfig)); |
| 1669 }· |
| 1670 else· |
| 1671 { |
| 1672 NS_LOG_LOGIC (this << " updating SIB19 for cell " << m_cellId); |
| 1673 it->second.haveSib19 = true; |
| 1674 it->second.sib19 = msg.sib19; |
| 1675 } |
| 1676 if (m_sidelinkConfiguration->IsMonitoringInterested() || m_sidelinkCon
figuration->IsAnnouncingInterested ())· |
| 1677 { |
| 1678 ············ |
| 1679 std::list< Ptr<SidelinkRxDiscResourcePool> > pools; |
| 1680 for (int i = 0 ; i < msg.sib19.discConfig.discRxPool.nbPools; i++) |
| 1681 { |
| 1682 Ptr<SidelinkRxDiscResourcePool> pool = NULL; |
| 1683 for (uint32_t j = 0 ; j < m_sidelinkConfiguration->monitorPools.si
ze() && pool == NULL; j++) |
| 1684 { |
| 1685 if (msg.sib19.discConfig.discRxPool.pools[i]== m_sidelinkConfigu
ration->monitorPools.at(j).first) |
| 1686 { |
| 1687 pool = m_sidelinkConfiguration->monitorPools.at(j).second; |
| 1688 } |
| 1689 }················ |
| 1690 if (pool == NULL) |
| 1691 { |
| 1692 pool = CreateObject <SidelinkRxDiscResourcePool> (); |
| 1693 pool->SetPool (msg.sib19.discConfig.discRxPool.pools[i]); |
| 1694 m_sidelinkConfiguration->monitorPools.push_back (std::make_pair(
msg.sib19.discConfig.discRxPool.pools[i], pool)); |
| 1695 } |
| 1696 pools.push_back (pool); |
| 1697 } |
| 1698 m_cmacSapProvider->SetSlRxPools (pools); |
| 1699 m_cphySapProvider->SetSlRxPools (pools); |
| 1700 ·········· |
| 1701 } |
| 1702 }//end case |
| 1703 break; |
| 1704 default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_SIB1,
IDLE_WAIT_SIB1 |
| 1705 // do nothing |
| 1706 break; |
| 1707 }//end switch |
| 1708 }//end if |
| 1709 } |
| 1710 |
| 1711 |
| 1712 void· |
| 1713 NistLteUeRrc::DoRecvNistRrcConnectionSetup (NistLteRrcSap::NistRrcConnectionSetu
p msg) |
| 1714 { |
| 1715 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1716 switch (m_state) |
| 1717 { |
| 1718 case IDLE_CONNECTING: |
| 1719 { |
| 1720 ApplyNistRadioResourceConfigDedicated (msg.radioResourceConfigDedicated)
; |
| 1721 m_connectionTimeout.Cancel (); |
| 1722 SwitchToState (CONNECTED_NORMALLY); |
| 1723 NistLteRrcSap::NistRrcConnectionSetupCompleted msg2; |
| 1724 msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier; |
| 1725 m_rrcSapUser->SendNistRrcConnectionSetupCompleted (msg2); |
| 1726 m_asSapUser->NotifyConnectionSuccessful (); |
| 1727 m_connectionEstablishedTrace (m_imsi, m_cellId, m_rnti); |
| 1728 } |
| 1729 break; |
| 1730 |
| 1731 default: |
| 1732 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1733 break; |
| 1734 } |
| 1735 } |
| 1736 |
| 1737 void |
| 1738 NistLteUeRrc::DoRecvNistRrcConnectionReconfiguration (NistLteRrcSap::NistRrcConn
ectionReconfiguration msg) |
| 1739 { |
| 1740 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1741 switch (m_state) |
| 1742 { |
| 1743 case CONNECTED_NORMALLY: |
| 1744 if (msg.haveNistMobilityControlInfo) |
| 1745 { |
| 1746 NS_LOG_INFO ("haveNistMobilityControlInfo == true"); |
| 1747 SwitchToState (CONNECTED_HANDOVER); |
| 1748 const NistLteRrcSap::NistMobilityControlInfo& mci = msg.mobilityContro
lInfo; |
| 1749 m_handoverStartTrace (m_imsi, m_cellId, m_rnti, mci.targetPhysCellId); |
| 1750 m_cmacSapProvider->Reset (); |
| 1751 m_cphySapProvider->Reset (); |
| 1752 m_cellId = mci.targetPhysCellId; |
| 1753 NS_ASSERT (mci.haveCarrierFreq); |
| 1754 NS_ASSERT (mci.haveCarrierBandwidth); |
| 1755 m_cphySapProvider->SynchronizeWithEnb (m_cellId, mci.carrierFreq.dlCar
rierFreq); |
| 1756 m_cphySapProvider->SetDlBandwidth ( mci.carrierBandwidth.dlBandwidth); |
| 1757 m_cphySapProvider->ConfigureUplink (mci.carrierFreq.ulCarrierFreq, mci
.carrierBandwidth.ulBandwidth);· |
| 1758 m_rnti = msg.mobilityControlInfo.newUeIdentity; |
| 1759 m_srb0->m_rlc->SetRnti (m_rnti); |
| 1760 NS_ASSERT_MSG (mci.haveNistRachConfigDedicated, "handover is only supp
orted with non-contention-based random access procedure"); |
| 1761 m_cmacSapProvider->StartNonContentionBasedRandomAccessProcedure (m_rnt
i, mci.rachConfigDedicated.raPreambleIndex, mci.rachConfigDedicated.raPrachMaskI
ndex); |
| 1762 m_cphySapProvider->SetRnti (m_rnti); |
| 1763 m_lastRrcTransactionIdentifier = msg.rrcTransactionIdentifier; |
| 1764 NS_ASSERT (msg.haveNistRadioResourceConfigDedicated); |
| 1765 |
| 1766 // we re-establish SRB1 by creating a new entity |
| 1767 // note that we can't dispose the old entity now, because |
| 1768 // it's in the current stack, so we would corrupt the stack |
| 1769 // if we did so. Hence we schedule it for later disposal |
| 1770 m_srb1Old = m_srb1; |
| 1771 Simulator::ScheduleNow (&NistLteUeRrc::DisposeOldSrb1, this); |
| 1772 m_srb1 = 0; // new instance will be be created within ApplyNistRadioRe
sourceConfigDedicated |
| 1773 |
| 1774 m_drbMap.clear (); // dispose all DRBs |
| 1775 ApplyNistRadioResourceConfigDedicated (msg.radioResourceConfigDedicate
d); |
| 1776 |
| 1777 if (msg.haveNistMeasConfig) |
| 1778 { |
| 1779 ApplyNistMeasConfig (msg.measConfig); |
| 1780 } |
| 1781 // RRC connection reconfiguration completed will be sent |
| 1782 // after handover is complete |
| 1783 } |
| 1784 else |
| 1785 { |
| 1786 NS_LOG_INFO ("haveNistMobilityControlInfo == false"); |
| 1787 if (msg.haveNistRadioResourceConfigDedicated) |
| 1788 { |
| 1789 ApplyNistRadioResourceConfigDedicated (msg.radioResourceConfigDedi
cated); |
| 1790 }· |
| 1791 if (msg.haveNistMeasConfig) |
| 1792 { |
| 1793 ApplyNistMeasConfig (msg.measConfig); |
| 1794 } |
| 1795 //check if it has sidelink resource information |
| 1796 if (msg.haveSlCommConfig) |
| 1797 { |
| 1798 ApplySidelinkDedicatedConfiguration (msg.slCommConfig); |
| 1799 } |
| 1800 //check if it has discovery resource information |
| 1801 if (msg.haveSlDiscConfig) |
| 1802 { |
| 1803 ApplySidelinkDedicatedConfiguration (msg.slDiscConfig); |
| 1804 } |
| 1805 |
| 1806 NistLteRrcSap::NistRrcConnectionReconfigurationCompleted msg2; |
| 1807 msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier; |
| 1808 m_rrcSapUser->SendNistRrcConnectionReconfigurationCompleted (msg2); |
| 1809 m_connectionReconfigurationTrace (m_imsi, m_cellId, m_rnti); |
| 1810 } |
| 1811 break; |
| 1812 |
| 1813 default: |
| 1814 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1815 break; |
| 1816 } |
| 1817 } |
| 1818 |
| 1819 void· |
| 1820 NistLteUeRrc::DoRecvNistRrcConnectionReestablishment (NistLteRrcSap::NistRrcConn
ectionReestablishment msg) |
| 1821 { |
| 1822 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1823 switch (m_state) |
| 1824 { |
| 1825 case CONNECTED_REESTABLISHING: |
| 1826 { |
| 1827 /** |
| 1828 * \todo After receiving RRC Connection Re-establishment, stop timer |
| 1829 * T301, fire a new trace source, reply with RRC Connection |
| 1830 * Re-establishment Complete, and finally switch to |
| 1831 * CONNECTED_NORMALLY state. See Section 5.3.7.5 of 3GPP TS |
| 1832 * 36.331. |
| 1833 */ |
| 1834 |
| 1835 |
| 1836 //if target cell sending SIB 18 or 19 and SidelinkUEInformation was sent
in the last second |
| 1837 //with interest/resource request, |
| 1838 //initiate transmission of the SidelinkUEInformation message in accordan
ce with 5.X.2.3 |
| 1839 if ((m_sidelinkConfiguration->IsCellBroadcastingSIB18 (m_cellId) || m_si
delinkConfiguration->IsCellBroadcastingSIB19 (m_cellId)) && m_sidelinkConfigurat
ion->GetTimeSinceLastTransmissionOfSidelinkUeInformation () < 1.0) { |
| 1840 SendSidelinkUeInformation (); |
| 1841 } |
| 1842 } |
| 1843 break; |
| 1844 |
| 1845 default: |
| 1846 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1847 break; |
| 1848 } |
| 1849 } |
| 1850 |
| 1851 void· |
| 1852 NistLteUeRrc::DoRecvNistRrcConnectionReestablishmentReject (NistLteRrcSap::NistR
rcConnectionReestablishmentReject msg) |
| 1853 { |
| 1854 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1855 switch (m_state) |
| 1856 { |
| 1857 case CONNECTED_REESTABLISHING: |
| 1858 { |
| 1859 /** |
| 1860 * \todo After receiving RRC Connection Re-establishment Reject, stop |
| 1861 * timer T301. See Section 5.3.7.8 of 3GPP TS 36.331. |
| 1862 */ |
| 1863 LeaveConnectedMode (); |
| 1864 } |
| 1865 break; |
| 1866 |
| 1867 default: |
| 1868 NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state)); |
| 1869 break; |
| 1870 } |
| 1871 } |
| 1872 |
| 1873 void· |
| 1874 NistLteUeRrc::DoRecvNistRrcConnectionRelease (NistLteRrcSap::NistRrcConnectionRe
lease msg) |
| 1875 { |
| 1876 NS_LOG_FUNCTION (this << " RNTI " << m_rnti); |
| 1877 /// \todo Currently not implemented, see Section 5.3.8 of 3GPP TS 36.331. |
| 1878 } |
| 1879 |
| 1880 void· |
| 1881 NistLteUeRrc::DoRecvNistRrcConnectionReject (NistLteRrcSap::NistRrcConnectionRej
ect msg) |
| 1882 { |
| 1883 NS_LOG_FUNCTION (this); |
| 1884 m_connectionTimeout.Cancel (); |
| 1885 |
| 1886 m_cmacSapProvider->Reset (); // reset the MAC |
| 1887 m_hasReceivedSib2 = false; // invalidate the previously received SIB2 |
| 1888 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 1889 m_asSapUser->NotifyConnectionFailed (); // inform upper layer |
| 1890 } |
| 1891 |
| 1892 |
| 1893 |
| 1894 void |
| 1895 NistLteUeRrc::SynchronizeToStrongestCell () |
| 1896 { |
| 1897 NS_LOG_FUNCTION (this); |
| 1898 NS_ASSERT (m_state == IDLE_CELL_SEARCH); |
| 1899 |
| 1900 uint16_t maxRsrpCellId = 0; |
| 1901 double maxRsrp = -std::numeric_limits<double>::infinity (); |
| 1902 |
| 1903 std::map<uint16_t, NistMeasValues>::iterator it; |
| 1904 for (it = m_storedNistMeasValues.begin (); it != m_storedNistMeasValues.end ()
; it++) |
| 1905 { |
| 1906 /* |
| 1907 * This block attempts to find a cell with strongest RSRP and has not |
| 1908 * yet been identified as "acceptable cell". |
| 1909 */ |
| 1910 if (maxRsrp < it->second.rsrp) |
| 1911 { |
| 1912 std::set<uint16_t>::const_iterator itCell; |
| 1913 itCell = m_acceptableCell.find (it->first); |
| 1914 if (itCell == m_acceptableCell.end ()) |
| 1915 { |
| 1916 maxRsrpCellId = it->first; |
| 1917 maxRsrp = it->second.rsrp; |
| 1918 } |
| 1919 } |
| 1920 } |
| 1921 |
| 1922 if (maxRsrpCellId == 0) |
| 1923 { |
| 1924 NS_LOG_WARN (this << " Cell search is unable to detect surrounding cell to
attach to"); |
| 1925 } |
| 1926 else |
| 1927 { |
| 1928 NS_LOG_LOGIC (this << " cell " << maxRsrpCellId |
| 1929 << " is the strongest untried surrounding cell"); |
| 1930 m_cphySapProvider->SynchronizeWithEnb (maxRsrpCellId, m_dlEarfcn); |
| 1931 SwitchToState (IDLE_WAIT_MIB_SIB1); |
| 1932 } |
| 1933 |
| 1934 } // end of void NistLteUeRrc::SynchronizeToStrongestCell () |
| 1935 |
| 1936 |
| 1937 void |
| 1938 NistLteUeRrc::EvaluateCellForSelection () |
| 1939 { |
| 1940 NS_LOG_FUNCTION (this); |
| 1941 NS_ASSERT (m_state == IDLE_WAIT_SIB1); |
| 1942 NS_ASSERT (m_hasReceivedMib); |
| 1943 NS_ASSERT (m_hasReceivedSib1); |
| 1944 uint16_t cellId = m_lastSib1.cellAccessRelatedInfo.cellIdentity; |
| 1945 |
| 1946 // Cell selection criteria evaluation |
| 1947 |
| 1948 bool isSuitableCell = false; |
| 1949 bool isAcceptableCell = false; |
| 1950 std::map<uint16_t, NistMeasValues>::iterator storedMeasIt = m_storedNistMeasVa
lues.find (cellId); |
| 1951 double qRxLevMeas = storedMeasIt->second.rsrp; |
| 1952 double qRxLevMin = NistEutranMeasurementMapping::IeValue2ActualQRxLevMin (m_la
stSib1.cellSelectionInfo.qRxLevMin); |
| 1953 NS_LOG_LOGIC (this << " cell selection to cellId=" << cellId |
| 1954 << " qrxlevmeas=" << qRxLevMeas << " dBm" |
| 1955 << " qrxlevmin=" << qRxLevMin << " dBm"); |
| 1956 |
| 1957 if (qRxLevMeas - qRxLevMin > 0) |
| 1958 { |
| 1959 isAcceptableCell = true; |
| 1960 |
| 1961 uint32_t cellCsgId = m_lastSib1.cellAccessRelatedInfo.csgIdentity; |
| 1962 bool cellCsgIndication = m_lastSib1.cellAccessRelatedInfo.csgIndication; |
| 1963 |
| 1964 isSuitableCell = (cellCsgIndication == false) || (cellCsgId == m_csgWhiteL
ist); |
| 1965 |
| 1966 NS_LOG_LOGIC (this << " csg(ue/cell/indication)=" << m_csgWhiteList << "/" |
| 1967 << cellCsgId << "/" << cellCsgIndication); |
| 1968 } |
| 1969 |
| 1970 // Cell selection decision |
| 1971 |
| 1972 if (isSuitableCell) |
| 1973 { |
| 1974 m_cellId = cellId; |
| 1975 m_cphySapProvider->SynchronizeWithEnb (cellId, m_dlEarfcn); |
| 1976 m_cphySapProvider->SetDlBandwidth (m_dlBandwidth); |
| 1977 m_initialCellSelectionEndOkTrace (m_imsi, cellId); |
| 1978 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 1979 } |
| 1980 else |
| 1981 { |
| 1982 // ignore the MIB and SIB1 received from this cell |
| 1983 m_hasReceivedMib = false; |
| 1984 m_hasReceivedSib1 = false; |
| 1985 |
| 1986 m_initialCellSelectionEndErrorTrace (m_imsi, cellId); |
| 1987 |
| 1988 if (isAcceptableCell) |
| 1989 { |
| 1990 /* |
| 1991 * The cells inserted into this list will not be considered for |
| 1992 * subsequent cell search attempt. |
| 1993 */ |
| 1994 m_acceptableCell.insert (cellId); |
| 1995 } |
| 1996 |
| 1997 SwitchToState (IDLE_CELL_SEARCH); |
| 1998 SynchronizeToStrongestCell (); // retry to a different cell |
| 1999 } |
| 2000 |
| 2001 } // end of void NistLteUeRrc::EvaluateCellForSelection () |
| 2002 |
| 2003 |
| 2004 void· |
| 2005 NistLteUeRrc::ApplyNistRadioResourceConfigDedicated (NistLteRrcSap::NistRadioRes
ourceConfigDedicated rrcd) |
| 2006 { |
| 2007 NS_LOG_FUNCTION (this); |
| 2008 const struct NistLteRrcSap::NistPhysicalConfigDedicated& pcd = rrcd.physicalCo
nfigDedicated; |
| 2009 |
| 2010 if (pcd.haveNistAntennaInfoDedicated) |
| 2011 { |
| 2012 m_cphySapProvider->SetTransmissionMode (pcd.antennaInfo.transmissionMode); |
| 2013 } |
| 2014 if (pcd.haveNistSoundingRsUlConfigDedicated) |
| 2015 { |
| 2016 m_cphySapProvider->SetSrsConfigurationIndex (pcd.soundingRsUlConfigDedicat
ed.srsConfigIndex); |
| 2017 } |
| 2018 |
| 2019 if (pcd.haveNistPdschConfigDedicated) |
| 2020 { |
| 2021 // update NistPdschConfigDedicated (i.e. P_A value) |
| 2022 m_pdschConfigDedicated = pcd.pdschConfigDedicated; |
| 2023 double paDouble = NistLteRrcSap::ConvertNistPdschConfigDedicated2Double (m
_pdschConfigDedicated); |
| 2024 m_cphySapProvider->SetPa (paDouble); |
| 2025 } |
| 2026 |
| 2027 std::list<NistLteRrcSap::NistSrbToAddMod>::const_iterator stamIt = rrcd.srbToA
ddModList.begin (); |
| 2028 if (stamIt != rrcd.srbToAddModList.end ()) |
| 2029 { |
| 2030 if (m_srb1 == 0) |
| 2031 { |
| 2032 // SRB1 not setup yet········ |
| 2033 NS_ASSERT_MSG ((m_state == IDLE_CONNECTING) || (m_state == CONNECTED_H
ANDOVER),· |
| 2034 "unexpected state " << ToString (m_state)); |
| 2035 NS_ASSERT_MSG (stamIt->srbIdentity == 1, "only SRB1 supported"); |
| 2036 |
| 2037 const uint8_t lcid = 1; // fixed LCID for SRB1 |
| 2038 |
| 2039 Ptr<NistLteRlc> rlc = CreateObject<NistLteRlcAm> (); |
| 2040 rlc->SetNistLteMacSapProvider (m_macSapProvider); |
| 2041 rlc->SetRnti (m_rnti); |
| 2042 rlc->SetLcId (lcid);······ |
| 2043 |
| 2044 Ptr<NistLtePdcp> pdcp = CreateObject<NistLtePdcp> (); |
| 2045 pdcp->SetRnti (m_rnti); |
| 2046 pdcp->SetLcId (lcid); |
| 2047 pdcp->SetNistLtePdcpSapUser (m_drbPdcpSapUser); |
| 2048 pdcp->SetNistLteRlcSapProvider (rlc->GetNistLteRlcSapProvider ()); |
| 2049 rlc->SetNistLteRlcSapUser (pdcp->GetNistLteRlcSapUser ()); |
| 2050 |
| 2051 m_srb1 = CreateObject<LteSignalingRadioNistBearerInfo> (); |
| 2052 m_srb1->m_rlc = rlc; |
| 2053 m_srb1->m_pdcp = pdcp; |
| 2054 m_srb1->m_srbIdentity = 1; |
| 2055 ·········· |
| 2056 m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig
.priority; |
| 2057 m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = stamIt->logica
lChannelConfig.prioritizedBitRateKbps; |
| 2058 m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = stamIt->logicalC
hannelConfig.bucketSizeDurationMs; |
| 2059 m_srb1->m_logicalChannelConfig.logicalChannelGroup = stamIt->logicalCh
annelConfig.logicalChannelGroup; |
| 2060 |
| 2061 struct NistLteUeCmacSapProvider::NistLogicalChannelConfig lcConfig; |
| 2062 lcConfig.priority = stamIt->logicalChannelConfig.priority; |
| 2063 lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.priorit
izedBitRateKbps; |
| 2064 lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSiz
eDurationMs; |
| 2065 lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalCha
nnelGroup; |
| 2066 ······ |
| 2067 m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetNistLteMacSapUser ()
); |
| 2068 ······ |
| 2069 ++stamIt; |
| 2070 NS_ASSERT_MSG (stamIt == rrcd.srbToAddModList.end (), "at most one Srb
ToAdd supported");····· |
| 2071 ·········· |
| 2072 NistLteUeRrcSapUser::NistSetupParameters ueParams; |
| 2073 ueParams.srb0SapProvider = m_srb0->m_rlc->GetNistLteRlcSapProvider (); |
| 2074 ueParams.srb1SapProvider = m_srb1->m_pdcp->GetNistLtePdcpSapProvider (
); |
| 2075 m_rrcSapUser->Setup (ueParams); |
| 2076 } |
| 2077 else |
| 2078 { |
| 2079 NS_LOG_INFO ("request to modify SRB1 (skipping as currently not implem
ented)"); |
| 2080 // would need to modify m_srb1, and then propagate changes to the MAC |
| 2081 } |
| 2082 } |
| 2083 |
| 2084 |
| 2085 std::list<NistLteRrcSap::NistDrbToAddMod>::const_iterator dtamIt; |
| 2086 for (dtamIt = rrcd.drbToAddModList.begin (); |
| 2087 dtamIt != rrcd.drbToAddModList.end (); |
| 2088 ++dtamIt) |
| 2089 { |
| 2090 NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << (
uint32_t) dtamIt->drbIdentity << " LC " << (uint32_t) dtamIt->logicalChannelIden
tity); |
| 2091 NS_ASSERT_MSG (dtamIt->logicalChannelIdentity > 2, "LCID value " << dtamIt
->logicalChannelIdentity << " is reserved for SRBs"); |
| 2092 |
| 2093 std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator drbMapIt = m
_drbMap.find (dtamIt->drbIdentity); |
| 2094 if (drbMapIt == m_drbMap.end ()) |
| 2095 { |
| 2096 NS_LOG_INFO ("New Data Radio Bearer"); |
| 2097 ········ |
| 2098 TypeId rlcTypeId; |
| 2099 if (m_useRlcSm) |
| 2100 { |
| 2101 rlcTypeId = NistLteRlcSm::GetTypeId (); |
| 2102 } |
| 2103 else |
| 2104 { |
| 2105 switch (dtamIt->rlcConfig.choice) |
| 2106 { |
| 2107 case NistLteRrcSap::NistRlcConfig::AM:· |
| 2108 rlcTypeId = NistLteRlcAm::GetTypeId (); |
| 2109 break; |
| 2110 ·········· |
| 2111 case NistLteRrcSap::NistRlcConfig::UM_BI_DIRECTIONAL:· |
| 2112 rlcTypeId = NistLteRlcUm::GetTypeId (); |
| 2113 break; |
| 2114 ·········· |
| 2115 default: |
| 2116 NS_FATAL_ERROR ("unsupported RLC configuration"); |
| 2117 break;················ |
| 2118 } |
| 2119 } |
| 2120 ·· |
| 2121 ObjectFactory rlcObjectFactory; |
| 2122 rlcObjectFactory.SetTypeId (rlcTypeId); |
| 2123 Ptr<NistLteRlc> rlc = rlcObjectFactory.Create ()->GetObject<NistLteRlc
> (); |
| 2124 rlc->SetNistLteMacSapProvider (m_macSapProvider); |
| 2125 rlc->SetRnti (m_rnti); |
| 2126 rlc->SetLcId (dtamIt->logicalChannelIdentity); |
| 2127 |
| 2128 Ptr<LteDataRadioNistBearerInfo> drbInfo = CreateObject<LteDataRadioNis
tBearerInfo> (); |
| 2129 drbInfo->m_rlc = rlc; |
| 2130 drbInfo->m_epsBearerIdentity = dtamIt->epsBearerIdentity; |
| 2131 drbInfo->m_logicalChannelIdentity = dtamIt->logicalChannelIdentity; |
| 2132 drbInfo->m_drbIdentity = dtamIt->drbIdentity; |
| 2133 · |
| 2134 // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM |
| 2135 // if we are using RLC/SM we don't care of anything above RLC |
| 2136 if (rlcTypeId != NistLteRlcSm::GetTypeId ()) |
| 2137 { |
| 2138 Ptr<NistLtePdcp> pdcp = CreateObject<NistLtePdcp> (); |
| 2139 pdcp->SetRnti (m_rnti); |
| 2140 pdcp->SetLcId (dtamIt->logicalChannelIdentity); |
| 2141 pdcp->SetNistLtePdcpSapUser (m_drbPdcpSapUser); |
| 2142 pdcp->SetNistLteRlcSapProvider (rlc->GetNistLteRlcSapProvider ()); |
| 2143 rlc->SetNistLteRlcSapUser (pdcp->GetNistLteRlcSapUser ()); |
| 2144 drbInfo->m_pdcp = pdcp; |
| 2145 } |
| 2146 |
| 2147 m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity; |
| 2148 ·· |
| 2149 m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioNistBearerInfo> >
(dtamIt->drbIdentity, drbInfo)); |
| 2150 ·· |
| 2151 |
| 2152 struct NistLteUeCmacSapProvider::NistLogicalChannelConfig lcConfig; |
| 2153 lcConfig.priority = dtamIt->logicalChannelConfig.priority; |
| 2154 lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.priorit
izedBitRateKbps; |
| 2155 lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSiz
eDurationMs; |
| 2156 lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalCha
nnelGroup;······ |
| 2157 |
| 2158 m_cmacSapProvider->AddLc (dtamIt->logicalChannelIdentity, |
| 2159 lcConfig, |
| 2160 rlc->GetNistLteMacSapUser ()); |
| 2161 // added function to handle priority in the lac layer of UE· |
| 2162 m_cmacSapProvider->AddLCPriority (m_rnti, dtamIt->logicalChannelIdenti
ty, dtamIt->logicalChannelConfig.priority); |
| 2163 rlc->Initialize (); |
| 2164 } |
| 2165 else |
| 2166 { |
| 2167 NS_LOG_INFO ("request to modify existing DRBID"); |
| 2168 Ptr<LteDataRadioNistBearerInfo> drbInfo = drbMapIt->second; |
| 2169 /// \todo currently not implemented. Would need to modify drbInfo, and
then propagate changes to the MAC |
| 2170 } |
| 2171 } |
| 2172 ·· |
| 2173 std::list<uint8_t>::iterator dtdmIt; |
| 2174 for (dtdmIt = rrcd.drbToReleaseList.begin (); |
| 2175 dtdmIt != rrcd.drbToReleaseList.end (); |
| 2176 ++dtdmIt) |
| 2177 { |
| 2178 uint8_t drbid = *dtdmIt; |
| 2179 NS_LOG_INFO (this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t)
drbid << drbid); |
| 2180 std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drb
Map.find (drbid); |
| 2181 NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with given lc
id"); |
| 2182 m_drbMap.erase (it);······ |
| 2183 m_bid2DrbidMap.erase (drbid); |
| 2184 //Remove LCID |
| 2185 m_cmacSapProvider->RemoveLc (drbid + 2); |
| 2186 } |
| 2187 } |
| 2188 |
| 2189 |
| 2190 void· |
| 2191 NistLteUeRrc::ApplyNistMeasConfig (NistLteRrcSap::NistMeasConfig mc) |
| 2192 { |
| 2193 NS_LOG_FUNCTION (this); |
| 2194 |
| 2195 // perform the actions specified in 3GPP TS 36.331 section 5.5.2.1· |
| 2196 |
| 2197 // 3GPP TS 36.331 section 5.5.2.4 Measurement object removal |
| 2198 for (std::list<uint8_t>::iterator it = mc.measObjectToRemoveList.begin (); |
| 2199 it != mc.measObjectToRemoveList.end (); |
| 2200 ++it) |
| 2201 { |
| 2202 uint8_t measObjectId = *it; |
| 2203 NS_LOG_LOGIC (this << " deleting measObjectId " << (uint32_t) measObjectI
d); |
| 2204 m_varNistMeasConfig.measObjectList.erase (measObjectId); |
| 2205 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measIdIt =
m_varNistMeasConfig.measIdList.begin (); |
| 2206 while (measIdIt != m_varNistMeasConfig.measIdList.end ()) |
| 2207 { |
| 2208 if (measIdIt->second.measObjectId == measObjectId) |
| 2209 { |
| 2210 uint8_t measId = measIdIt->second.measId; |
| 2211 NS_ASSERT (measId == measIdIt->first); |
| 2212 NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId <<
" because referring to measObjectId " << (uint32_t) measObjectId); |
| 2213 // note: postfix operator preserves iterator validity |
| 2214 m_varNistMeasConfig.measIdList.erase (measIdIt++); |
| 2215 NistVarMeasReportListClear (measId); |
| 2216 } |
| 2217 else |
| 2218 { |
| 2219 ++measIdIt; |
| 2220 } |
| 2221 } |
| 2222 |
| 2223 } |
| 2224 |
| 2225 // 3GPP TS 36.331 section 5.5.2.5 Measurement object addition/ modification |
| 2226 for (std::list<NistLteRrcSap::NistMeasObjectToAddMod>::iterator it = mc.measOb
jectToAddModList.begin (); |
| 2227 it != mc.measObjectToAddModList.end (); |
| 2228 ++it) |
| 2229 { |
| 2230 // simplifying assumptions |
| 2231 NS_ASSERT_MSG (it->measObjectEutra.cellsToRemoveList.empty (), "cellsToRem
oveList not supported"); |
| 2232 NS_ASSERT_MSG (it->measObjectEutra.cellsToAddModList.empty (), "cellsToAdd
ModList not supported"); |
| 2233 NS_ASSERT_MSG (it->measObjectEutra.cellsToRemoveList.empty (), "blackCells
ToRemoveList not supported"); |
| 2234 NS_ASSERT_MSG (it->measObjectEutra.blackNistCellsToAddModList.empty (), "b
lackNistCellsToAddModList not supported"); |
| 2235 NS_ASSERT_MSG (it->measObjectEutra.haveCellForWhichToReportCGI == false, "
cellForWhichToReportCGI is not supported"); |
| 2236 |
| 2237 uint8_t measObjectId = it->measObjectId; |
| 2238 std::map<uint8_t, NistLteRrcSap::NistMeasObjectToAddMod>::iterator measObj
ectIt = m_varNistMeasConfig.measObjectList.find (measObjectId); |
| 2239 if (measObjectIt != m_varNistMeasConfig.measObjectList.end ()) |
| 2240 { |
| 2241 NS_LOG_LOGIC ("measObjectId " << (uint32_t) measObjectId << " exists,
updating entry"); |
| 2242 measObjectIt->second = *it; |
| 2243 for (std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator me
asIdIt· |
| 2244 = m_varNistMeasConfig.measIdList.begin (); |
| 2245 measIdIt != m_varNistMeasConfig.measIdList.end (); |
| 2246 ++measIdIt) |
| 2247 { |
| 2248 if (measIdIt->second.measObjectId == measObjectId) |
| 2249 { |
| 2250 uint8_t measId = measIdIt->second.measId; |
| 2251 NS_LOG_LOGIC (this << " found measId " << (uint32_t) measId <<
" referring to measObjectId " << (uint32_t) measObjectId); |
| 2252 NistVarMeasReportListClear (measId); |
| 2253 } |
| 2254 } |
| 2255 } |
| 2256 else |
| 2257 { |
| 2258 NS_LOG_LOGIC ("measObjectId " << (uint32_t) measObjectId << " is new,
adding entry"); |
| 2259 m_varNistMeasConfig.measObjectList[measObjectId] = *it; |
| 2260 } |
| 2261 |
| 2262 } |
| 2263 |
| 2264 // 3GPP TS 36.331 section 5.5.2.6 Reporting configuration removal |
| 2265 for (std::list<uint8_t>::iterator it = mc.reportConfigToRemoveList.begin (); |
| 2266 it != mc.reportConfigToRemoveList.end (); |
| 2267 ++it) |
| 2268 { |
| 2269 uint8_t reportConfigId = *it; |
| 2270 NS_LOG_LOGIC (this << " deleting reportConfigId " << (uint32_t) reportCon
figId); |
| 2271 m_varNistMeasConfig.reportConfigList.erase (reportConfigId); |
| 2272 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measIdIt =
m_varNistMeasConfig.measIdList.begin (); |
| 2273 while (measIdIt != m_varNistMeasConfig.measIdList.end ()) |
| 2274 { |
| 2275 if (measIdIt->second.reportConfigId == reportConfigId) |
| 2276 { |
| 2277 uint8_t measId = measIdIt->second.measId; |
| 2278 NS_ASSERT (measId == measIdIt->first); |
| 2279 NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId <<
" because referring to reportConfigId " << (uint32_t) reportConfigId); |
| 2280 // note: postfix operator preserves iterator validity |
| 2281 m_varNistMeasConfig.measIdList.erase (measIdIt++); |
| 2282 NistVarMeasReportListClear (measId); |
| 2283 } |
| 2284 else |
| 2285 { |
| 2286 ++measIdIt; |
| 2287 } |
| 2288 } |
| 2289 |
| 2290 } |
| 2291 |
| 2292 // 3GPP TS 36.331 section 5.5.2.7 Reporting configuration addition/ modificati
on |
| 2293 for (std::list<NistLteRrcSap::NistReportConfigToAddMod>::iterator it = mc.repo
rtConfigToAddModList.begin (); |
| 2294 it != mc.reportConfigToAddModList.end (); |
| 2295 ++it) |
| 2296 { |
| 2297 // simplifying assumptions |
| 2298 NS_ASSERT_MSG (it->reportConfigEutra.triggerType == NistLteRrcSap::NistRep
ortConfigEutra::EVENT, |
| 2299 "only trigger type EVENT is supported"); |
| 2300 |
| 2301 uint8_t reportConfigId = it->reportConfigId; |
| 2302 std::map<uint8_t, NistLteRrcSap::NistReportConfigToAddMod>::iterator repor
tConfigIt = m_varNistMeasConfig.reportConfigList.find (reportConfigId); |
| 2303 if (reportConfigIt != m_varNistMeasConfig.reportConfigList.end ()) |
| 2304 { |
| 2305 NS_LOG_LOGIC ("reportConfigId " << (uint32_t) reportConfigId << " exis
ts, updating entry"); |
| 2306 m_varNistMeasConfig.reportConfigList[reportConfigId] = *it; |
| 2307 for (std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator me
asIdIt· |
| 2308 = m_varNistMeasConfig.measIdList.begin (); |
| 2309 measIdIt != m_varNistMeasConfig.measIdList.end (); |
| 2310 ++measIdIt) |
| 2311 { |
| 2312 if (measIdIt->second.reportConfigId == reportConfigId) |
| 2313 { |
| 2314 uint8_t measId = measIdIt->second.measId; |
| 2315 NS_LOG_LOGIC (this << " found measId " << (uint32_t) measId <<
" referring to reportConfigId " << (uint32_t) reportConfigId); |
| 2316 NistVarMeasReportListClear (measId); |
| 2317 } |
| 2318 } |
| 2319 } |
| 2320 else |
| 2321 { |
| 2322 NS_LOG_LOGIC ("reportConfigId " << (uint32_t) reportConfigId << " is n
ew, adding entry"); |
| 2323 m_varNistMeasConfig.reportConfigList[reportConfigId] = *it; |
| 2324 } |
| 2325 |
| 2326 } |
| 2327 |
| 2328 // 3GPP TS 36.331 section 5.5.2.8 Quantity configuration |
| 2329 if (mc.haveNistQuantityConfig) |
| 2330 { |
| 2331 NS_LOG_LOGIC (this << " setting quantityConfig"); |
| 2332 m_varNistMeasConfig.quantityConfig = mc.quantityConfig; |
| 2333 // we calculate here the coefficient a used for Layer 3 filtering, see 3GP
P TS 36.331 section 5.5.3.2 |
| 2334 m_varNistMeasConfig.aRsrp = std::pow (0.5, mc.quantityConfig.filterCoeffic
ientRSRP / 4.0); |
| 2335 m_varNistMeasConfig.aRsrq = std::pow (0.5, mc.quantityConfig.filterCoeffic
ientRSRQ / 4.0); |
| 2336 NS_LOG_LOGIC (this << " new filter coefficients: aRsrp=" << m_varNistMeasC
onfig.aRsrp << ", aRsrq=" << m_varNistMeasConfig.aRsrq); |
| 2337 |
| 2338 for (std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measId
It |
| 2339 = m_varNistMeasConfig.measIdList.begin (); |
| 2340 measIdIt != m_varNistMeasConfig.measIdList.end (); |
| 2341 ++measIdIt) |
| 2342 { |
| 2343 NistVarMeasReportListClear (measIdIt->second.measId); |
| 2344 } |
| 2345 } |
| 2346 |
| 2347 // 3GPP TS 36.331 section 5.5.2.2 Measurement identity removal |
| 2348 for (std::list<uint8_t>::iterator it = mc.measIdToRemoveList.begin (); |
| 2349 it != mc.measIdToRemoveList.end (); |
| 2350 ++it) |
| 2351 { |
| 2352 uint8_t measId = *it; |
| 2353 NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId); |
| 2354 m_varNistMeasConfig.measIdList.erase (measId); |
| 2355 NistVarMeasReportListClear (measId); |
| 2356 |
| 2357 // removing time-to-trigger queues |
| 2358 m_enteringTriggerQueue.erase (measId); |
| 2359 m_leavingTriggerQueue.erase (measId); |
| 2360 } |
| 2361 |
| 2362 // 3GPP TS 36.331 section 5.5.2.3 Measurement identity addition/ modification |
| 2363 for (std::list<NistLteRrcSap::NistMeasIdToAddMod>::iterator it = mc.measIdToAd
dModList.begin (); |
| 2364 it != mc.measIdToAddModList.end (); |
| 2365 ++it) |
| 2366 { |
| 2367 NS_LOG_LOGIC (this << " measId " << (uint32_t) it->measId |
| 2368 << " (measObjectId=" << (uint32_t) it->measObjectId |
| 2369 << ", reportConfigId=" << (uint32_t) it->reportConfigId |
| 2370 << ")"); |
| 2371 NS_ASSERT (m_varNistMeasConfig.measObjectList.find (it->measObjectId) |
| 2372 != m_varNistMeasConfig.measObjectList.end ()); |
| 2373 NS_ASSERT (m_varNistMeasConfig.reportConfigList.find (it->reportConfigId) |
| 2374 != m_varNistMeasConfig.reportConfigList.end ()); |
| 2375 m_varNistMeasConfig.measIdList[it->measId] = *it; // side effect: create n
ew entry if not exists |
| 2376 std::map<uint8_t, NistVarMeasReport>::iterator measReportIt = m_varMeasRep
ortList.find (it->measId); |
| 2377 if (measReportIt != m_varMeasReportList.end ()) |
| 2378 { |
| 2379 measReportIt->second.periodicReportTimer.Cancel (); |
| 2380 m_varMeasReportList.erase (measReportIt); |
| 2381 } |
| 2382 NS_ASSERT (m_varNistMeasConfig.reportConfigList.find (it->reportConfigId) |
| 2383 ->second.reportConfigEutra.triggerType != NistLteRrcSap::NistRe
portConfigEutra::PERIODICAL); |
| 2384 |
| 2385 // new empty queues for time-to-trigger |
| 2386 std::list<NistPendingTrigger_t> s; |
| 2387 m_enteringTriggerQueue[it->measId] = s; |
| 2388 m_leavingTriggerQueue[it->measId] = s; |
| 2389 } |
| 2390 |
| 2391 if (mc.haveNistMeasGapConfig) |
| 2392 { |
| 2393 NS_FATAL_ERROR ("measurement gaps are currently not supported"); |
| 2394 } |
| 2395 |
| 2396 if (mc.haveSmeasure) |
| 2397 { |
| 2398 NS_FATAL_ERROR ("s-measure is currently not supported"); |
| 2399 } |
| 2400 |
| 2401 if (mc.haveNistSpeedStatePars) |
| 2402 { |
| 2403 NS_FATAL_ERROR ("NistSpeedStatePars are currently not supported"); |
| 2404 } |
| 2405 } |
| 2406 |
| 2407 void |
| 2408 NistLteUeRrc::SaveNistUeMeasurements (uint16_t cellId, double rsrp, double rsrq, |
| 2409 bool useLayer3Filtering) |
| 2410 { |
| 2411 NS_LOG_FUNCTION (this << cellId << rsrp << rsrq << useLayer3Filtering); |
| 2412 |
| 2413 std::map<uint16_t, NistMeasValues>::iterator storedMeasIt = m_storedNistMeasVa
lues.find (cellId); |
| 2414 |
| 2415 if (storedMeasIt != m_storedNistMeasValues.end ()) |
| 2416 { |
| 2417 if (useLayer3Filtering) |
| 2418 { |
| 2419 // F_n = (1-a) F_{n-1} + a M_n |
| 2420 storedMeasIt->second.rsrp = (1 - m_varNistMeasConfig.aRsrp) * storedMe
asIt->second.rsrp |
| 2421 + m_varNistMeasConfig.aRsrp * rsrp; |
| 2422 |
| 2423 if (std::isnan (storedMeasIt->second.rsrq)) |
| 2424 { |
| 2425 // the previous RSRQ measurements provided UE PHY are invalid |
| 2426 storedMeasIt->second.rsrq = rsrq; // replace it with unfiltered va
lue |
| 2427 } |
| 2428 else |
| 2429 { |
| 2430 storedMeasIt->second.rsrq = (1 - m_varNistMeasConfig.aRsrq) * stor
edMeasIt->second.rsrq |
| 2431 + m_varNistMeasConfig.aRsrq * rsrq; |
| 2432 } |
| 2433 } |
| 2434 else |
| 2435 { |
| 2436 storedMeasIt->second.rsrp = rsrp; |
| 2437 storedMeasIt->second.rsrq = rsrq; |
| 2438 } |
| 2439 } |
| 2440 else |
| 2441 { |
| 2442 // first value is always unfiltered |
| 2443 NistMeasValues v; |
| 2444 v.rsrp = rsrp; |
| 2445 v.rsrq = rsrq; |
| 2446 std::pair<uint16_t, NistMeasValues> val (cellId, v); |
| 2447 std::pair<std::map<uint16_t, NistMeasValues>::iterator, bool> |
| 2448 ret = m_storedNistMeasValues.insert (val); |
| 2449 NS_ASSERT_MSG (ret.second == true, "element already existed"); |
| 2450 storedMeasIt = ret.first; |
| 2451 } |
| 2452 |
| 2453 NS_LOG_DEBUG (this << " IMSI " << m_imsi << " state " << ToString (m_state) |
| 2454 << ", measured cell " << m_cellId |
| 2455 << ", new RSRP " << rsrp << " stored " << storedMeasIt->sec
ond.rsrp |
| 2456 << ", new RSRQ " << rsrq << " stored " << storedMeasIt->sec
ond.rsrq); |
| 2457 storedMeasIt->second.timestamp = Simulator::Now (); |
| 2458 |
| 2459 } // end of void SaveNistUeMeasurements |
| 2460 |
| 2461 void |
| 2462 NistLteUeRrc::NistMeasurementReportTriggering (uint8_t measId) |
| 2463 { |
| 2464 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 2465 |
| 2466 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator measIdIt = |
| 2467 m_varNistMeasConfig.measIdList.find (measId); |
| 2468 NS_ASSERT (measIdIt != m_varNistMeasConfig.measIdList.end ()); |
| 2469 NS_ASSERT (measIdIt->first == measIdIt->second.measId); |
| 2470 |
| 2471 std::map<uint8_t, NistLteRrcSap::NistReportConfigToAddMod>::iterator |
| 2472 reportConfigIt = m_varNistMeasConfig.reportConfigList.find (measIdIt->second
.reportConfigId); |
| 2473 NS_ASSERT (reportConfigIt != m_varNistMeasConfig.reportConfigList.end ()); |
| 2474 NistLteRrcSap::NistReportConfigEutra& reportConfigEutra = reportConfigIt->seco
nd.reportConfigEutra; |
| 2475 |
| 2476 std::map<uint8_t, NistLteRrcSap::NistMeasObjectToAddMod>::iterator |
| 2477 measObjectIt = m_varNistMeasConfig.measObjectList.find (measIdIt->second.mea
sObjectId); |
| 2478 NS_ASSERT (measObjectIt != m_varNistMeasConfig.measObjectList.end ()); |
| 2479 NistLteRrcSap::NistMeasObjectEutra& measObjectEutra = measObjectIt->second.mea
sObjectEutra; |
| 2480 |
| 2481 std::map<uint8_t, NistVarMeasReport>::iterator |
| 2482 measReportIt = m_varMeasReportList.find (measId); |
| 2483 bool isMeasIdInReportList = (measReportIt != m_varMeasReportList.end ()); |
| 2484 |
| 2485 // we don't check the purpose field, as it is only included for |
| 2486 // triggerType == periodical, which is not supported |
| 2487 NS_ASSERT_MSG (reportConfigEutra.triggerType |
| 2488 == NistLteRrcSap::NistReportConfigEutra::EVENT, |
| 2489 "only triggerType == event is supported"); |
| 2490 // only EUTRA is supported, no need to check for it |
| 2491 |
| 2492 NS_LOG_LOGIC (this << " considering measId " << (uint32_t) measId); |
| 2493 bool eventEntryCondApplicable = false; |
| 2494 bool eventLeavingCondApplicable = false; |
| 2495 ConcernedCells_t concernedCellsEntry; |
| 2496 ConcernedCells_t concernedCellsLeaving; |
| 2497 |
| 2498 switch (reportConfigEutra.eventId) |
| 2499 { |
| 2500 case NistLteRrcSap::NistReportConfigEutra::EVENT_A1: |
| 2501 { |
| 2502 /* |
| 2503 * Event A1 (Serving becomes better than threshold) |
| 2504 * Please refer to 3GPP TS 36.331 Section 5.5.4.2 |
| 2505 */ |
| 2506 |
| 2507 double ms; // Ms, the measurement result of the serving cell |
| 2508 double thresh; // Thresh, the threshold parameter for this event |
| 2509 // Hys, the hysteresis parameter for this event. |
| 2510 double hys = NistEutranMeasurementMapping::IeValue2ActualHysteresis (rep
ortConfigEutra.hysteresis); |
| 2511 |
| 2512 switch (reportConfigEutra.triggerQuantity) |
| 2513 { |
| 2514 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2515 ms = m_storedNistMeasValues[m_cellId].rsrp; |
| 2516 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2517 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2518 thresh = NistEutranMeasurementMapping::RsrpRange2Dbm (reportConfigEu
tra.threshold1.range); |
| 2519 break; |
| 2520 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2521 ms = m_storedNistMeasValues[m_cellId].rsrq; |
| 2522 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2523 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2524 thresh = NistEutranMeasurementMapping::RsrqRange2Db (reportConfigEut
ra.threshold1.range); |
| 2525 break; |
| 2526 default: |
| 2527 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2528 break; |
| 2529 } |
| 2530 |
| 2531 // Inequality A1-1 (Entering condition): Ms - Hys > Thresh |
| 2532 bool entryCond = ms - hys > thresh; |
| 2533 |
| 2534 if (entryCond) |
| 2535 { |
| 2536 if (!isMeasIdInReportList) |
| 2537 { |
| 2538 concernedCellsEntry.push_back (m_cellId); |
| 2539 eventEntryCondApplicable = true; |
| 2540 } |
| 2541 else |
| 2542 { |
| 2543 /* |
| 2544 * This is to check that the triggered cell recorded in the |
| 2545 * NistVarMeasReportList is the serving cell. |
| 2546 */ |
| 2547 NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellI
d) |
| 2548 != measReportIt->second.cellsTriggeredList.end ()); |
| 2549 } |
| 2550 } |
| 2551 else if (reportConfigEutra.timeToTrigger > 0) |
| 2552 { |
| 2553 CancelEnteringTrigger (measId); |
| 2554 } |
| 2555 |
| 2556 // Inequality A1-2 (Leaving condition): Ms + Hys < Thresh |
| 2557 bool leavingCond = ms + hys < thresh; |
| 2558 |
| 2559 if (leavingCond) |
| 2560 { |
| 2561 if (isMeasIdInReportList) |
| 2562 { |
| 2563 /* |
| 2564 * This is to check that the triggered cell recorded in the |
| 2565 * NistVarMeasReportList is the serving cell. |
| 2566 */ |
| 2567 NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellI
d) |
| 2568 != measReportIt->second.cellsTriggeredList.end ()); |
| 2569 concernedCellsLeaving.push_back (m_cellId); |
| 2570 eventLeavingCondApplicable = true; |
| 2571 } |
| 2572 } |
| 2573 else if (reportConfigEutra.timeToTrigger > 0) |
| 2574 { |
| 2575 CancelLeavingTrigger (measId); |
| 2576 } |
| 2577 |
| 2578 NS_LOG_LOGIC (this << " event A1: serving cell " << m_cellId |
| 2579 << " ms=" << ms << " thresh=" << thresh |
| 2580 << " entryCond=" << entryCond |
| 2581 << " leavingCond=" << leavingCond); |
| 2582 |
| 2583 } // end of case NistLteRrcSap::NistReportConfigEutra::EVENT_A1 |
| 2584 |
| 2585 break; |
| 2586 |
| 2587 case NistLteRrcSap::NistReportConfigEutra::EVENT_A2: |
| 2588 { |
| 2589 /* |
| 2590 * Event A2 (Serving becomes worse than threshold) |
| 2591 * Please refer to 3GPP TS 36.331 Section 5.5.4.3 |
| 2592 */ |
| 2593 |
| 2594 double ms; // Ms, the measurement result of the serving cell |
| 2595 double thresh; // Thresh, the threshold parameter for this event |
| 2596 // Hys, the hysteresis parameter for this event. |
| 2597 double hys = NistEutranMeasurementMapping::IeValue2ActualHysteresis (rep
ortConfigEutra.hysteresis); |
| 2598 |
| 2599 switch (reportConfigEutra.triggerQuantity) |
| 2600 { |
| 2601 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2602 ms = m_storedNistMeasValues[m_cellId].rsrp; |
| 2603 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2604 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2605 thresh = NistEutranMeasurementMapping::RsrpRange2Dbm (reportConfigEu
tra.threshold1.range); |
| 2606 break; |
| 2607 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2608 ms = m_storedNistMeasValues[m_cellId].rsrq; |
| 2609 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2610 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2611 thresh = NistEutranMeasurementMapping::RsrqRange2Db (reportConfigEut
ra.threshold1.range); |
| 2612 break; |
| 2613 default: |
| 2614 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2615 break; |
| 2616 } |
| 2617 |
| 2618 // Inequality A2-1 (Entering condition): Ms + Hys < Thresh |
| 2619 bool entryCond = ms + hys < thresh; |
| 2620 |
| 2621 if (entryCond) |
| 2622 { |
| 2623 if (!isMeasIdInReportList) |
| 2624 { |
| 2625 concernedCellsEntry.push_back (m_cellId); |
| 2626 eventEntryCondApplicable = true; |
| 2627 } |
| 2628 else |
| 2629 { |
| 2630 /* |
| 2631 * This is to check that the triggered cell recorded in the |
| 2632 * NistVarMeasReportList is the serving cell. |
| 2633 */ |
| 2634 NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellI
d) |
| 2635 != measReportIt->second.cellsTriggeredList.end ()); |
| 2636 } |
| 2637 } |
| 2638 else if (reportConfigEutra.timeToTrigger > 0) |
| 2639 { |
| 2640 CancelEnteringTrigger (measId); |
| 2641 } |
| 2642 |
| 2643 // Inequality A2-2 (Leaving condition): Ms - Hys > Thresh |
| 2644 bool leavingCond = ms - hys > thresh; |
| 2645 |
| 2646 if (leavingCond) |
| 2647 { |
| 2648 if (isMeasIdInReportList) |
| 2649 { |
| 2650 /* |
| 2651 * This is to check that the triggered cell recorded in the |
| 2652 * NistVarMeasReportList is the serving cell. |
| 2653 */ |
| 2654 NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellI
d) |
| 2655 != measReportIt->second.cellsTriggeredList.end ()); |
| 2656 concernedCellsLeaving.push_back (m_cellId); |
| 2657 eventLeavingCondApplicable = true; |
| 2658 } |
| 2659 } |
| 2660 else if (reportConfigEutra.timeToTrigger > 0) |
| 2661 { |
| 2662 CancelLeavingTrigger (measId); |
| 2663 } |
| 2664 |
| 2665 NS_LOG_LOGIC (this << " event A2: serving cell " << m_cellId |
| 2666 << " ms=" << ms << " thresh=" << thresh |
| 2667 << " entryCond=" << entryCond |
| 2668 << " leavingCond=" << leavingCond); |
| 2669 |
| 2670 } // end of case NistLteRrcSap::NistReportConfigEutra::EVENT_A2 |
| 2671 |
| 2672 break; |
| 2673 |
| 2674 case NistLteRrcSap::NistReportConfigEutra::EVENT_A3: |
| 2675 { |
| 2676 /* |
| 2677 * Event A3 (Neighbour becomes offset better than PCell) |
| 2678 * Please refer to 3GPP TS 36.331 Section 5.5.4.4 |
| 2679 */ |
| 2680 |
| 2681 double mn; // Mn, the measurement result of the neighbouring cell |
| 2682 double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific
offset of the frequency of the |
| 2683 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell |
| 2684 double mp; // Mp, the measurement result of the PCell |
| 2685 double ofp = measObjectEutra.offsetFreq; // Ofp, the frequency specific
offset of the primary frequency |
| 2686 double ocp = 0.0; // Ocp, the cell specific offset of the PCell |
| 2687 // Off, the offset parameter for this event. |
| 2688 double off = NistEutranMeasurementMapping::IeValue2ActualA3Offset (repor
tConfigEutra.a3Offset); |
| 2689 // Hys, the hysteresis parameter for this event. |
| 2690 double hys = NistEutranMeasurementMapping::IeValue2ActualHysteresis (rep
ortConfigEutra.hysteresis); |
| 2691 |
| 2692 switch (reportConfigEutra.triggerQuantity) |
| 2693 { |
| 2694 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2695 mp = m_storedNistMeasValues[m_cellId].rsrp; |
| 2696 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2697 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2698 break; |
| 2699 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2700 mp = m_storedNistMeasValues[m_cellId].rsrq; |
| 2701 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2702 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2703 break; |
| 2704 default: |
| 2705 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2706 break; |
| 2707 } |
| 2708 |
| 2709 for (std::map<uint16_t, NistMeasValues>::iterator storedMeasIt = m_store
dNistMeasValues.begin (); |
| 2710 storedMeasIt != m_storedNistMeasValues.end (); |
| 2711 ++storedMeasIt) |
| 2712 { |
| 2713 uint16_t cellId = storedMeasIt->first; |
| 2714 if (cellId == m_cellId) |
| 2715 { |
| 2716 continue; |
| 2717 } |
| 2718 |
| 2719 switch (reportConfigEutra.triggerQuantity) |
| 2720 { |
| 2721 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2722 mn = storedMeasIt->second.rsrp; |
| 2723 break; |
| 2724 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2725 mn = storedMeasIt->second.rsrq; |
| 2726 break; |
| 2727 default: |
| 2728 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2729 break; |
| 2730 } |
| 2731 |
| 2732 bool hasTriggered = isMeasIdInReportList |
| 2733 && (measReportIt->second.cellsTriggeredList.find (cellId) |
| 2734 != measReportIt->second.cellsTriggeredList.end ()); |
| 2735 |
| 2736 // Inequality A3-1 (Entering condition): Mn + Ofn + Ocn - Hys > Mp +
Ofp + Ocp + Off |
| 2737 bool entryCond = mn + ofn + ocn - hys > mp + ofp + ocp + off; |
| 2738 |
| 2739 if (entryCond) |
| 2740 { |
| 2741 if (!hasTriggered) |
| 2742 { |
| 2743 concernedCellsEntry.push_back (cellId); |
| 2744 eventEntryCondApplicable = true; |
| 2745 } |
| 2746 } |
| 2747 else if (reportConfigEutra.timeToTrigger > 0) |
| 2748 { |
| 2749 CancelEnteringTrigger (measId, cellId); |
| 2750 } |
| 2751 |
| 2752 // Inequality A3-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Mp +
Ofp + Ocp + Off |
| 2753 bool leavingCond = mn + ofn + ocn + hys < mp + ofp + ocp + off; |
| 2754 |
| 2755 if (leavingCond) |
| 2756 { |
| 2757 if (hasTriggered) |
| 2758 { |
| 2759 concernedCellsLeaving.push_back (cellId); |
| 2760 eventLeavingCondApplicable = true; |
| 2761 } |
| 2762 } |
| 2763 else if (reportConfigEutra.timeToTrigger > 0) |
| 2764 { |
| 2765 CancelLeavingTrigger (measId, cellId); |
| 2766 } |
| 2767 |
| 2768 NS_LOG_LOGIC (this << " event A3: neighbor cell " << cellId |
| 2769 << " mn=" << mn << " mp=" << mp << " offset=" <<
off |
| 2770 << " entryCond=" << entryCond |
| 2771 << " leavingCond=" << leavingCond); |
| 2772 |
| 2773 } // end of for (storedMeasIt) |
| 2774 |
| 2775 } // end of case NistLteRrcSap::NistReportConfigEutra::EVENT_A3 |
| 2776 |
| 2777 break; |
| 2778 |
| 2779 case NistLteRrcSap::NistReportConfigEutra::EVENT_A4: |
| 2780 { |
| 2781 /* |
| 2782 * Event A4 (Neighbour becomes better than threshold) |
| 2783 * Please refer to 3GPP TS 36.331 Section 5.5.4.5 |
| 2784 */ |
| 2785 |
| 2786 double mn; // Mn, the measurement result of the neighbouring cell |
| 2787 double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific
offset of the frequency of the |
| 2788 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell |
| 2789 double thresh; // Thresh, the threshold parameter for this event |
| 2790 // Hys, the hysteresis parameter for this event. |
| 2791 double hys = NistEutranMeasurementMapping::IeValue2ActualHysteresis (rep
ortConfigEutra.hysteresis); |
| 2792 |
| 2793 switch (reportConfigEutra.triggerQuantity) |
| 2794 { |
| 2795 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2796 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2797 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2798 thresh = NistEutranMeasurementMapping::RsrpRange2Dbm (reportConfigEu
tra.threshold1.range); |
| 2799 break; |
| 2800 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2801 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2802 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2803 thresh = NistEutranMeasurementMapping::RsrqRange2Db (reportConfigEut
ra.threshold1.range); |
| 2804 break; |
| 2805 default: |
| 2806 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2807 break; |
| 2808 } |
| 2809 |
| 2810 for (std::map<uint16_t, NistMeasValues>::iterator storedMeasIt = m_store
dNistMeasValues.begin (); |
| 2811 storedMeasIt != m_storedNistMeasValues.end (); |
| 2812 ++storedMeasIt) |
| 2813 { |
| 2814 uint16_t cellId = storedMeasIt->first; |
| 2815 if (cellId == m_cellId) |
| 2816 { |
| 2817 continue; |
| 2818 } |
| 2819 |
| 2820 switch (reportConfigEutra.triggerQuantity) |
| 2821 { |
| 2822 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2823 mn = storedMeasIt->second.rsrp; |
| 2824 break; |
| 2825 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2826 mn = storedMeasIt->second.rsrq; |
| 2827 break; |
| 2828 default: |
| 2829 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2830 break; |
| 2831 } |
| 2832 |
| 2833 bool hasTriggered = isMeasIdInReportList |
| 2834 && (measReportIt->second.cellsTriggeredList.find (cellId) |
| 2835 != measReportIt->second.cellsTriggeredList.end ()); |
| 2836 |
| 2837 // Inequality A4-1 (Entering condition): Mn + Ofn + Ocn - Hys > Thre
sh |
| 2838 bool entryCond = mn + ofn + ocn - hys > thresh; |
| 2839 |
| 2840 if (entryCond) |
| 2841 { |
| 2842 if (!hasTriggered) |
| 2843 { |
| 2844 concernedCellsEntry.push_back (cellId); |
| 2845 eventEntryCondApplicable = true; |
| 2846 } |
| 2847 } |
| 2848 else if (reportConfigEutra.timeToTrigger > 0) |
| 2849 { |
| 2850 CancelEnteringTrigger (measId, cellId); |
| 2851 } |
| 2852 |
| 2853 // Inequality A4-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Thres
h |
| 2854 bool leavingCond = mn + ofn + ocn + hys < thresh; |
| 2855 |
| 2856 if (leavingCond) |
| 2857 { |
| 2858 if (hasTriggered) |
| 2859 { |
| 2860 concernedCellsLeaving.push_back (cellId); |
| 2861 eventLeavingCondApplicable = true; |
| 2862 } |
| 2863 } |
| 2864 else if (reportConfigEutra.timeToTrigger > 0) |
| 2865 { |
| 2866 CancelLeavingTrigger (measId, cellId); |
| 2867 } |
| 2868 |
| 2869 NS_LOG_LOGIC (this << " event A4: neighbor cell " << cellId |
| 2870 << " mn=" << mn << " thresh=" << thresh |
| 2871 << " entryCond=" << entryCond |
| 2872 << " leavingCond=" << leavingCond); |
| 2873 |
| 2874 } // end of for (storedMeasIt) |
| 2875 |
| 2876 } // end of case NistLteRrcSap::NistReportConfigEutra::EVENT_A4 |
| 2877 |
| 2878 break; |
| 2879 |
| 2880 case NistLteRrcSap::NistReportConfigEutra::EVENT_A5: |
| 2881 { |
| 2882 /* |
| 2883 * Event A5 (PCell becomes worse than threshold1 and neighbour |
| 2884 * becomes better than threshold2) |
| 2885 * Please refer to 3GPP TS 36.331 Section 5.5.4.6 |
| 2886 */ |
| 2887 |
| 2888 double mp; // Mp, the measurement result of the PCell |
| 2889 double mn; // Mn, the measurement result of the neighbouring cell |
| 2890 double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific
offset of the frequency of the |
| 2891 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell |
| 2892 double thresh1; // Thresh1, the threshold parameter for this event |
| 2893 double thresh2; // Thresh2, the threshold parameter for this event |
| 2894 // Hys, the hysteresis parameter for this event. |
| 2895 double hys = NistEutranMeasurementMapping::IeValue2ActualHysteresis (rep
ortConfigEutra.hysteresis); |
| 2896 |
| 2897 switch (reportConfigEutra.triggerQuantity) |
| 2898 { |
| 2899 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2900 mp = m_storedNistMeasValues[m_cellId].rsrp; |
| 2901 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2902 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2903 NS_ASSERT (reportConfigEutra.threshold2.choice |
| 2904 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP); |
| 2905 thresh1 = NistEutranMeasurementMapping::RsrpRange2Dbm (reportConfigE
utra.threshold1.range); |
| 2906 thresh2 = NistEutranMeasurementMapping::RsrpRange2Dbm (reportConfigE
utra.threshold2.range); |
| 2907 break; |
| 2908 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2909 mp = m_storedNistMeasValues[m_cellId].rsrq; |
| 2910 NS_ASSERT (reportConfigEutra.threshold1.choice |
| 2911 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2912 NS_ASSERT (reportConfigEutra.threshold2.choice |
| 2913 == NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ); |
| 2914 thresh1 = NistEutranMeasurementMapping::RsrqRange2Db (reportConfigEu
tra.threshold1.range); |
| 2915 thresh2 = NistEutranMeasurementMapping::RsrqRange2Db (reportConfigEu
tra.threshold2.range); |
| 2916 break; |
| 2917 default: |
| 2918 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2919 break; |
| 2920 } |
| 2921 |
| 2922 // Inequality A5-1 (Entering condition 1): Mp + Hys < Thresh1 |
| 2923 bool entryCond = mp + hys < thresh1; |
| 2924 |
| 2925 if (entryCond) |
| 2926 { |
| 2927 for (std::map<uint16_t, NistMeasValues>::iterator storedMeasIt = m_s
toredNistMeasValues.begin (); |
| 2928 storedMeasIt != m_storedNistMeasValues.end (); |
| 2929 ++storedMeasIt) |
| 2930 { |
| 2931 uint16_t cellId = storedMeasIt->first; |
| 2932 if (cellId == m_cellId) |
| 2933 { |
| 2934 continue; |
| 2935 } |
| 2936 |
| 2937 switch (reportConfigEutra.triggerQuantity) |
| 2938 { |
| 2939 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 2940 mn = storedMeasIt->second.rsrp; |
| 2941 break; |
| 2942 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 2943 mn = storedMeasIt->second.rsrq; |
| 2944 break; |
| 2945 default: |
| 2946 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 2947 break; |
| 2948 } |
| 2949 |
| 2950 bool hasTriggered = isMeasIdInReportList |
| 2951 && (measReportIt->second.cellsTriggeredList.find (cellId) |
| 2952 != measReportIt->second.cellsTriggeredList.end ()); |
| 2953 |
| 2954 // Inequality A5-2 (Entering condition 2): Mn + Ofn + Ocn - Hys
> Thresh2 |
| 2955 |
| 2956 entryCond = mn + ofn + ocn - hys > thresh2; |
| 2957 |
| 2958 if (entryCond) |
| 2959 { |
| 2960 if (!hasTriggered) |
| 2961 { |
| 2962 concernedCellsEntry.push_back (cellId); |
| 2963 eventEntryCondApplicable = true; |
| 2964 } |
| 2965 } |
| 2966 else if (reportConfigEutra.timeToTrigger > 0) |
| 2967 { |
| 2968 CancelEnteringTrigger (measId, cellId); |
| 2969 } |
| 2970 |
| 2971 NS_LOG_LOGIC (this << " event A5: neighbor cell " << cellId |
| 2972 << " mn=" << mn << " mp=" << mp |
| 2973 << " thresh2=" << thresh2 |
| 2974 << " thresh1=" << thresh1 |
| 2975 << " entryCond=" << entryCond); |
| 2976 |
| 2977 } // end of for (storedMeasIt) |
| 2978 |
| 2979 } // end of if (entryCond) |
| 2980 else |
| 2981 { |
| 2982 NS_LOG_LOGIC (this << " event A5: serving cell " << m_cellId |
| 2983 << " mp=" << mp << " thresh1=" << thresh1 |
| 2984 << " entryCond=" << entryCond); |
| 2985 |
| 2986 if (reportConfigEutra.timeToTrigger > 0) |
| 2987 { |
| 2988 CancelEnteringTrigger (measId); |
| 2989 } |
| 2990 } |
| 2991 |
| 2992 if (isMeasIdInReportList) |
| 2993 { |
| 2994 // Inequality A5-3 (Leaving condition 1): Mp - Hys > Thresh1 |
| 2995 bool leavingCond = mp - hys > thresh1; |
| 2996 |
| 2997 if (leavingCond) |
| 2998 { |
| 2999 if (reportConfigEutra.timeToTrigger == 0) |
| 3000 { |
| 3001 // leaving condition #2 does not have to be checked |
| 3002 |
| 3003 for (std::map<uint16_t, NistMeasValues>::iterator storedMeas
It = m_storedNistMeasValues.begin (); |
| 3004 storedMeasIt != m_storedNistMeasValues.end (); |
| 3005 ++storedMeasIt) |
| 3006 { |
| 3007 uint16_t cellId = storedMeasIt->first; |
| 3008 if (cellId == m_cellId) |
| 3009 { |
| 3010 continue; |
| 3011 } |
| 3012 |
| 3013 if (measReportIt->second.cellsTriggeredList.find (cellId
) |
| 3014 != measReportIt->second.cellsTriggeredList.end ()) |
| 3015 { |
| 3016 concernedCellsLeaving.push_back (cellId); |
| 3017 eventLeavingCondApplicable = true; |
| 3018 } |
| 3019 } |
| 3020 } // end of if (reportConfigEutra.timeToTrigger == 0) |
| 3021 else |
| 3022 { |
| 3023 // leaving condition #2 has to be checked to cancel time-to-
trigger |
| 3024 |
| 3025 for (std::map<uint16_t, NistMeasValues>::iterator storedMeas
It = m_storedNistMeasValues.begin (); |
| 3026 storedMeasIt != m_storedNistMeasValues.end (); |
| 3027 ++storedMeasIt) |
| 3028 { |
| 3029 uint16_t cellId = storedMeasIt->first; |
| 3030 if (cellId == m_cellId) |
| 3031 { |
| 3032 continue; |
| 3033 } |
| 3034 |
| 3035 if (measReportIt->second.cellsTriggeredList.find (cellId
) |
| 3036 != measReportIt->second.cellsTriggeredList.end ()) |
| 3037 { |
| 3038 switch (reportConfigEutra.triggerQuantity) |
| 3039 { |
| 3040 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 3041 mn = storedMeasIt->second.rsrp; |
| 3042 break; |
| 3043 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 3044 mn = storedMeasIt->second.rsrq; |
| 3045 break; |
| 3046 default: |
| 3047 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 3048 break; |
| 3049 } |
| 3050 |
| 3051 // Inequality A5-4 (Leaving condition 2): Mn + Ofn +
Ocn + Hys < Thresh2 |
| 3052 |
| 3053 leavingCond = mn + ofn + ocn + hys < thresh2; |
| 3054 |
| 3055 if (!leavingCond) |
| 3056 { |
| 3057 CancelLeavingTrigger (measId, cellId); |
| 3058 } |
| 3059 |
| 3060 /* |
| 3061 * Whatever the result of leaving condition #2, this |
| 3062 * cell is still "in", because leaving condition #1 |
| 3063 * is already true. |
| 3064 */ |
| 3065 concernedCellsLeaving.push_back (cellId); |
| 3066 eventLeavingCondApplicable = true; |
| 3067 |
| 3068 NS_LOG_LOGIC (this << " event A5: neighbor cell " <<
cellId |
| 3069 << " mn=" << mn << " mp=" << mp |
| 3070 << " thresh2=" << thresh2 |
| 3071 << " thresh1=" << thresh1 |
| 3072 << " leavingCond=" << leavingCond
); |
| 3073 |
| 3074 } // end of if (measReportIt->second.cellsTriggeredLis
t.find (cellId) |
| 3075 // != measReportIt->second.cellsTriggered
List.end ()) |
| 3076 |
| 3077 } // end of for (storedMeasIt) |
| 3078 |
| 3079 } // end of else of if (reportConfigEutra.timeToTrigger == 0) |
| 3080 |
| 3081 NS_LOG_LOGIC (this << " event A5: serving cell " << m_cellId |
| 3082 << " mp=" << mp << " thresh1=" << thresh1 |
| 3083 << " leavingCond=" << leavingCond); |
| 3084 |
| 3085 } // end of if (leavingCond) |
| 3086 else |
| 3087 { |
| 3088 if (reportConfigEutra.timeToTrigger > 0) |
| 3089 { |
| 3090 CancelLeavingTrigger (measId); |
| 3091 } |
| 3092 |
| 3093 // check leaving condition #2 |
| 3094 |
| 3095 for (std::map<uint16_t, NistMeasValues>::iterator storedMeasIt =
m_storedNistMeasValues.begin (); |
| 3096 storedMeasIt != m_storedNistMeasValues.end (); |
| 3097 ++storedMeasIt) |
| 3098 { |
| 3099 uint16_t cellId = storedMeasIt->first; |
| 3100 if (cellId == m_cellId) |
| 3101 { |
| 3102 continue; |
| 3103 } |
| 3104 |
| 3105 if (measReportIt->second.cellsTriggeredList.find (cellId) |
| 3106 != measReportIt->second.cellsTriggeredList.end ()) |
| 3107 { |
| 3108 switch (reportConfigEutra.triggerQuantity) |
| 3109 { |
| 3110 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 3111 mn = storedMeasIt->second.rsrp; |
| 3112 break; |
| 3113 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 3114 mn = storedMeasIt->second.rsrq; |
| 3115 break; |
| 3116 default: |
| 3117 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 3118 break; |
| 3119 } |
| 3120 |
| 3121 // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn
+ Hys < Thresh2 |
| 3122 leavingCond = mn + ofn + ocn + hys < thresh2; |
| 3123 |
| 3124 if (leavingCond) |
| 3125 { |
| 3126 concernedCellsLeaving.push_back (cellId); |
| 3127 eventLeavingCondApplicable = true; |
| 3128 } |
| 3129 |
| 3130 NS_LOG_LOGIC (this << " event A5: neighbor cell " << cel
lId |
| 3131 << " mn=" << mn << " mp=" << mp |
| 3132 << " thresh2=" << thresh2 |
| 3133 << " thresh1=" << thresh1 |
| 3134 << " leavingCond=" << leavingCond); |
| 3135 |
| 3136 } // end of if (measReportIt->second.cellsTriggeredList.fi
nd (cellId) |
| 3137 // != measReportIt->second.cellsTriggeredList
.end ()) |
| 3138 |
| 3139 } // end of for (storedMeasIt) |
| 3140 |
| 3141 } // end of else of if (leavingCond) |
| 3142 |
| 3143 } // end of if (isMeasIdInReportList) |
| 3144 |
| 3145 } // end of case NistLteRrcSap::NistReportConfigEutra::EVENT_A5 |
| 3146 |
| 3147 break; |
| 3148 |
| 3149 default: |
| 3150 NS_FATAL_ERROR ("unsupported eventId " << reportConfigEutra.eventId); |
| 3151 break; |
| 3152 |
| 3153 } // switch (event type) |
| 3154 |
| 3155 NS_LOG_LOGIC (this << " eventEntryCondApplicable=" << eventEntryCondApplicable |
| 3156 << " eventLeavingCondApplicable=" << eventLeavingCondApplic
able); |
| 3157 |
| 3158 if (eventEntryCondApplicable) |
| 3159 { |
| 3160 if (reportConfigEutra.timeToTrigger == 0) |
| 3161 { |
| 3162 NistVarMeasReportListAdd (measId, concernedCellsEntry); |
| 3163 } |
| 3164 else |
| 3165 { |
| 3166 NistPendingTrigger_t t; |
| 3167 t.measId = measId; |
| 3168 t.concernedCells = concernedCellsEntry; |
| 3169 t.timer = Simulator::Schedule (MilliSeconds (reportConfigEutra.timeToT
rigger), |
| 3170 &NistLteUeRrc::NistVarMeasReportListAdd
, this, |
| 3171 measId, concernedCellsEntry); |
| 3172 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3173 enteringTriggerIt = m_enteringTriggerQueue.find (measId); |
| 3174 NS_ASSERT (enteringTriggerIt != m_enteringTriggerQueue.end ()); |
| 3175 enteringTriggerIt->second.push_back (t); |
| 3176 } |
| 3177 } |
| 3178 |
| 3179 if (eventLeavingCondApplicable) |
| 3180 { |
| 3181 // reportOnLeave will only be set when eventId = eventA3 |
| 3182 bool reportOnLeave = (reportConfigEutra.eventId == NistLteRrcSap::NistRepo
rtConfigEutra::EVENT_A3) |
| 3183 && reportConfigEutra.reportOnLeave; |
| 3184 |
| 3185 if (reportConfigEutra.timeToTrigger == 0) |
| 3186 { |
| 3187 NistVarMeasReportListErase (measId, concernedCellsLeaving, reportOnLea
ve); |
| 3188 } |
| 3189 else |
| 3190 { |
| 3191 NistPendingTrigger_t t; |
| 3192 t.measId = measId; |
| 3193 t.concernedCells = concernedCellsLeaving; |
| 3194 t.timer = Simulator::Schedule (MilliSeconds (reportConfigEutra.timeToT
rigger), |
| 3195 &NistLteUeRrc::NistVarMeasReportListEra
se, this, |
| 3196 measId, concernedCellsLeaving, reportOn
Leave); |
| 3197 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3198 leavingTriggerIt = m_leavingTriggerQueue.find (measId); |
| 3199 NS_ASSERT (leavingTriggerIt != m_leavingTriggerQueue.end ()); |
| 3200 leavingTriggerIt->second.push_back (t); |
| 3201 } |
| 3202 } |
| 3203 |
| 3204 } // end of void NistLteUeRrc::NistMeasurementReportTriggering (uint8_t measId) |
| 3205 |
| 3206 void |
| 3207 NistLteUeRrc::CancelEnteringTrigger (uint8_t measId) |
| 3208 { |
| 3209 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3210 |
| 3211 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3212 it1 = m_enteringTriggerQueue.find (measId); |
| 3213 NS_ASSERT (it1 != m_enteringTriggerQueue.end ()); |
| 3214 |
| 3215 if (!it1->second.empty ()) |
| 3216 { |
| 3217 std::list<NistPendingTrigger_t>::iterator it2; |
| 3218 for (it2 = it1->second.begin (); it2 != it1->second.end (); ++it2) |
| 3219 { |
| 3220 NS_ASSERT (it2->measId == measId); |
| 3221 NS_LOG_LOGIC (this << " canceling entering time-to-trigger event at " |
| 3222 << Simulator::GetDelayLeft (it2->timer).GetSeconds
()); |
| 3223 Simulator::Cancel (it2->timer); |
| 3224 } |
| 3225 |
| 3226 it1->second.clear (); |
| 3227 } |
| 3228 } |
| 3229 |
| 3230 void |
| 3231 NistLteUeRrc::CancelEnteringTrigger (uint8_t measId, uint16_t cellId) |
| 3232 { |
| 3233 NS_LOG_FUNCTION (this << (uint16_t) measId << cellId); |
| 3234 |
| 3235 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3236 it1 = m_enteringTriggerQueue.find (measId); |
| 3237 NS_ASSERT (it1 != m_enteringTriggerQueue.end ()); |
| 3238 |
| 3239 std::list<NistPendingTrigger_t>::iterator it2 = it1->second.begin (); |
| 3240 while (it2 != it1->second.end ()) |
| 3241 { |
| 3242 NS_ASSERT (it2->measId == measId); |
| 3243 |
| 3244 ConcernedCells_t::iterator it3; |
| 3245 for (it3 = it2->concernedCells.begin (); |
| 3246 it3 != it2->concernedCells.end (); ++it3) |
| 3247 { |
| 3248 if (*it3 == cellId) |
| 3249 { |
| 3250 it3 = it2->concernedCells.erase (it3); |
| 3251 } |
| 3252 } |
| 3253 |
| 3254 if (it2->concernedCells.empty ()) |
| 3255 { |
| 3256 NS_LOG_LOGIC (this << " canceling entering time-to-trigger event at " |
| 3257 << Simulator::GetDelayLeft (it2->timer).GetSeconds
()); |
| 3258 Simulator::Cancel (it2->timer); |
| 3259 it2 = it1->second.erase (it2); |
| 3260 } |
| 3261 else |
| 3262 { |
| 3263 it2++; |
| 3264 } |
| 3265 } |
| 3266 } |
| 3267 |
| 3268 void |
| 3269 NistLteUeRrc::CancelLeavingTrigger (uint8_t measId) |
| 3270 { |
| 3271 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3272 |
| 3273 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3274 it1 = m_leavingTriggerQueue.find (measId); |
| 3275 NS_ASSERT (it1 != m_leavingTriggerQueue.end ()); |
| 3276 |
| 3277 if (!it1->second.empty ()) |
| 3278 { |
| 3279 std::list<NistPendingTrigger_t>::iterator it2; |
| 3280 for (it2 = it1->second.begin (); it2 != it1->second.end (); ++it2) |
| 3281 { |
| 3282 NS_ASSERT (it2->measId == measId); |
| 3283 NS_LOG_LOGIC (this << " canceling leaving time-to-trigger event at " |
| 3284 << Simulator::GetDelayLeft (it2->timer).GetSeconds
()); |
| 3285 Simulator::Cancel (it2->timer); |
| 3286 } |
| 3287 |
| 3288 it1->second.clear (); |
| 3289 } |
| 3290 } |
| 3291 |
| 3292 void |
| 3293 NistLteUeRrc::CancelLeavingTrigger (uint8_t measId, uint16_t cellId) |
| 3294 { |
| 3295 NS_LOG_FUNCTION (this << (uint16_t) measId << cellId); |
| 3296 |
| 3297 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3298 it1 = m_leavingTriggerQueue.find (measId); |
| 3299 NS_ASSERT (it1 != m_leavingTriggerQueue.end ()); |
| 3300 |
| 3301 std::list<NistPendingTrigger_t>::iterator it2 = it1->second.begin (); |
| 3302 while (it2 != it1->second.end ()) |
| 3303 { |
| 3304 NS_ASSERT (it2->measId == measId); |
| 3305 |
| 3306 ConcernedCells_t::iterator it3; |
| 3307 for (it3 = it2->concernedCells.begin (); |
| 3308 it3 != it2->concernedCells.end (); ++it3) |
| 3309 { |
| 3310 if (*it3 == cellId) |
| 3311 { |
| 3312 it3 = it2->concernedCells.erase (it3); |
| 3313 } |
| 3314 } |
| 3315 |
| 3316 if (it2->concernedCells.empty ()) |
| 3317 { |
| 3318 NS_LOG_LOGIC (this << " canceling leaving time-to-trigger event at " |
| 3319 << Simulator::GetDelayLeft (it2->timer).GetSeconds
()); |
| 3320 Simulator::Cancel (it2->timer); |
| 3321 it2 = it1->second.erase (it2); |
| 3322 } |
| 3323 else |
| 3324 { |
| 3325 it2++; |
| 3326 } |
| 3327 } |
| 3328 } |
| 3329 |
| 3330 void |
| 3331 NistLteUeRrc::NistVarMeasReportListAdd (uint8_t measId, ConcernedCells_t enterin
gCells) |
| 3332 { |
| 3333 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3334 NS_ASSERT (!enteringCells.empty ()); |
| 3335 |
| 3336 std::map<uint8_t, NistVarMeasReport>::iterator |
| 3337 measReportIt = m_varMeasReportList.find (measId); |
| 3338 |
| 3339 if (measReportIt == m_varMeasReportList.end ()) |
| 3340 { |
| 3341 NistVarMeasReport r; |
| 3342 r.measId = measId; |
| 3343 std::pair<uint8_t, NistVarMeasReport> val (measId, r); |
| 3344 std::pair<std::map<uint8_t, NistVarMeasReport>::iterator, bool> |
| 3345 ret = m_varMeasReportList.insert (val); |
| 3346 NS_ASSERT_MSG (ret.second == true, "element already existed"); |
| 3347 measReportIt = ret.first; |
| 3348 } |
| 3349 |
| 3350 NS_ASSERT (measReportIt != m_varMeasReportList.end ()); |
| 3351 |
| 3352 for (ConcernedCells_t::const_iterator it = enteringCells.begin (); |
| 3353 it != enteringCells.end (); |
| 3354 ++it) |
| 3355 { |
| 3356 measReportIt->second.cellsTriggeredList.insert (*it); |
| 3357 } |
| 3358 |
| 3359 NS_ASSERT (!measReportIt->second.cellsTriggeredList.empty ()); |
| 3360 measReportIt->second.numberOfReportsSent = 0; |
| 3361 measReportIt->second.periodicReportTimer |
| 3362 = Simulator::Schedule (UE_MEASUREMENT_REPORT_DELAY, |
| 3363 &NistLteUeRrc::SendNistMeasurementReport, |
| 3364 this, measId); |
| 3365 |
| 3366 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3367 enteringTriggerIt = m_enteringTriggerQueue.find (measId); |
| 3368 NS_ASSERT (enteringTriggerIt != m_enteringTriggerQueue.end ()); |
| 3369 if (!enteringTriggerIt->second.empty ()) |
| 3370 { |
| 3371 /* |
| 3372 * Assumptions at this point: |
| 3373 * - the call to this function was delayed by time-to-trigger; |
| 3374 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and |
| 3375 * - the first element in the list is associated with this function call. |
| 3376 */ |
| 3377 enteringTriggerIt->second.pop_front (); |
| 3378 |
| 3379 if (!enteringTriggerIt->second.empty ()) |
| 3380 { |
| 3381 /* |
| 3382 * To prevent the same set of cells triggering again in the future, |
| 3383 * we clean up the time-to-trigger queue. This case might occur when |
| 3384 * time-to-trigger > 200 ms. |
| 3385 */ |
| 3386 for (ConcernedCells_t::const_iterator it = enteringCells.begin (); |
| 3387 it != enteringCells.end (); ++it) |
| 3388 { |
| 3389 CancelEnteringTrigger (measId, *it); |
| 3390 } |
| 3391 } |
| 3392 |
| 3393 } // end of if (!enteringTriggerIt->second.empty ()) |
| 3394 |
| 3395 } // end of NistLteUeRrc::NistVarMeasReportListAdd |
| 3396 |
| 3397 void |
| 3398 NistLteUeRrc::NistVarMeasReportListErase (uint8_t measId, ConcernedCells_t leavi
ngCells, |
| 3399 bool reportOnLeave) |
| 3400 { |
| 3401 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3402 NS_ASSERT (!leavingCells.empty ()); |
| 3403 |
| 3404 std::map<uint8_t, NistVarMeasReport>::iterator |
| 3405 measReportIt = m_varMeasReportList.find (measId); |
| 3406 NS_ASSERT (measReportIt != m_varMeasReportList.end ()); |
| 3407 |
| 3408 for (ConcernedCells_t::const_iterator it = leavingCells.begin (); |
| 3409 it != leavingCells.end (); |
| 3410 ++it) |
| 3411 { |
| 3412 measReportIt->second.cellsTriggeredList.erase (*it); |
| 3413 } |
| 3414 |
| 3415 if (reportOnLeave) |
| 3416 { |
| 3417 // runs immediately without UE_MEASUREMENT_REPORT_DELAY |
| 3418 SendNistMeasurementReport (measId); |
| 3419 } |
| 3420 |
| 3421 if (measReportIt->second.cellsTriggeredList.empty ()) |
| 3422 { |
| 3423 measReportIt->second.periodicReportTimer.Cancel (); |
| 3424 m_varMeasReportList.erase (measReportIt); |
| 3425 } |
| 3426 |
| 3427 std::map<uint8_t, std::list<NistPendingTrigger_t> >::iterator |
| 3428 leavingTriggerIt = m_leavingTriggerQueue.find (measId); |
| 3429 NS_ASSERT (leavingTriggerIt != m_leavingTriggerQueue.end ()); |
| 3430 if (!leavingTriggerIt->second.empty ()) |
| 3431 { |
| 3432 /* |
| 3433 * Assumptions at this point: |
| 3434 * - the call to this function was delayed by time-to-trigger; and |
| 3435 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and |
| 3436 * - the first element in the list is associated with this function call. |
| 3437 */ |
| 3438 leavingTriggerIt->second.pop_front (); |
| 3439 |
| 3440 if (!leavingTriggerIt->second.empty ()) |
| 3441 { |
| 3442 /* |
| 3443 * To prevent the same set of cells triggering again in the future, |
| 3444 * we clean up the time-to-trigger queue. This case might occur when |
| 3445 * time-to-trigger > 200 ms. |
| 3446 */ |
| 3447 for (ConcernedCells_t::const_iterator it = leavingCells.begin (); |
| 3448 it != leavingCells.end (); ++it) |
| 3449 { |
| 3450 CancelLeavingTrigger (measId, *it); |
| 3451 } |
| 3452 } |
| 3453 |
| 3454 } // end of if (!leavingTriggerIt->second.empty ()) |
| 3455 |
| 3456 } // end of NistLteUeRrc::NistVarMeasReportListErase |
| 3457 |
| 3458 void |
| 3459 NistLteUeRrc::NistVarMeasReportListClear (uint8_t measId) |
| 3460 { |
| 3461 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3462 |
| 3463 // remove the measurement reporting entry for this measId from the NistVarMeas
ReportList |
| 3464 std::map<uint8_t, NistVarMeasReport>::iterator |
| 3465 measReportIt = m_varMeasReportList.find (measId); |
| 3466 if (measReportIt != m_varMeasReportList.end ()) |
| 3467 { |
| 3468 NS_LOG_LOGIC (this << " deleting existing report for measId " << (uint16_t
) measId); |
| 3469 measReportIt->second.periodicReportTimer.Cancel (); |
| 3470 m_varMeasReportList.erase (measReportIt); |
| 3471 } |
| 3472 |
| 3473 CancelEnteringTrigger (measId); |
| 3474 CancelLeavingTrigger (measId); |
| 3475 } |
| 3476 |
| 3477 void· |
| 3478 NistLteUeRrc::SendNistMeasurementReport (uint8_t measId) |
| 3479 { |
| 3480 NS_LOG_FUNCTION (this << (uint16_t) measId); |
| 3481 // 3GPP TS 36.331 section 5.5.5 Measurement reporting |
| 3482 |
| 3483 std::map<uint8_t, NistLteRrcSap::NistMeasIdToAddMod>::iterator· |
| 3484 measIdIt = m_varNistMeasConfig.measIdList.find (measId); |
| 3485 NS_ASSERT (measIdIt != m_varNistMeasConfig.measIdList.end ()); |
| 3486 |
| 3487 std::map<uint8_t, NistLteRrcSap::NistReportConfigToAddMod>::iterator· |
| 3488 reportConfigIt = m_varNistMeasConfig.reportConfigList.find (measIdIt->second
.reportConfigId); |
| 3489 NS_ASSERT (reportConfigIt != m_varNistMeasConfig.reportConfigList.end ()); |
| 3490 NistLteRrcSap::NistReportConfigEutra& reportConfigEutra = reportConfigIt->seco
nd.reportConfigEutra; |
| 3491 |
| 3492 NistLteRrcSap::NistMeasurementReport measurementReport; |
| 3493 NistLteRrcSap::NistMeasResults& measResults = measurementReport.measResults; |
| 3494 measResults.measId = measId; |
| 3495 |
| 3496 std::map<uint16_t, NistMeasValues>::iterator servingMeasIt = m_storedNistMeasV
alues.find (m_cellId); |
| 3497 NS_ASSERT (servingMeasIt != m_storedNistMeasValues.end ()); |
| 3498 measResults.rsrpResult = NistEutranMeasurementMapping::Dbm2RsrpRange (servingM
easIt->second.rsrp); |
| 3499 measResults.rsrqResult = NistEutranMeasurementMapping::Db2RsrqRange (servingMe
asIt->second.rsrq); |
| 3500 NS_LOG_INFO (this << " reporting serving cell " |
| 3501 "RSRP " << (uint32_t) measResults.rsrpResult << " (" << servingMe
asIt->second.rsrp << " dBm) " |
| 3502 "RSRQ " << (uint32_t) measResults.rsrqResult << " (" << servingMe
asIt->second.rsrq << " dB)"); |
| 3503 measResults.haveMeasResultNeighCells = false; |
| 3504 std::map<uint8_t, NistVarMeasReport>::iterator measReportIt = m_varMeasReportL
ist.find (measId); |
| 3505 if (measReportIt == m_varMeasReportList.end ()) |
| 3506 { |
| 3507 NS_LOG_ERROR ("no entry found in m_varMeasReportList for measId " << (uint
32_t) measId); |
| 3508 } |
| 3509 else |
| 3510 { |
| 3511 if (!(measReportIt->second.cellsTriggeredList.empty ())) |
| 3512 { |
| 3513 std::multimap<double, uint16_t> sortedNeighCells; |
| 3514 for (std::set<uint16_t>::iterator cellsTriggeredIt = measReportIt->sec
ond.cellsTriggeredList.begin (); |
| 3515 cellsTriggeredIt != measReportIt->second.cellsTriggeredList.end (
); |
| 3516 ++cellsTriggeredIt) |
| 3517 { |
| 3518 uint16_t cellId = *cellsTriggeredIt; |
| 3519 if (cellId != m_cellId) |
| 3520 { |
| 3521 std::map<uint16_t, NistMeasValues>::iterator neighborMeasIt =
m_storedNistMeasValues.find (cellId); |
| 3522 double triggerValue; |
| 3523 switch (reportConfigEutra.triggerQuantity) |
| 3524 { |
| 3525 case NistLteRrcSap::NistReportConfigEutra::RSRP: |
| 3526 triggerValue = neighborMeasIt->second.rsrp; |
| 3527 break; |
| 3528 case NistLteRrcSap::NistReportConfigEutra::RSRQ: |
| 3529 triggerValue = neighborMeasIt->second.rsrq; |
| 3530 break; |
| 3531 default: |
| 3532 NS_FATAL_ERROR ("unsupported triggerQuantity"); |
| 3533 break; |
| 3534 } |
| 3535 sortedNeighCells.insert (std::pair<double, uint16_t> (triggerV
alue, cellId)); |
| 3536 } |
| 3537 } |
| 3538 |
| 3539 std::multimap<double, uint16_t>::reverse_iterator sortedNeighCellsIt; |
| 3540 uint32_t count; |
| 3541 for (sortedNeighCellsIt = sortedNeighCells.rbegin (), count = 0; |
| 3542 sortedNeighCellsIt != sortedNeighCells.rend () && count < reportC
onfigEutra.maxReportCells; |
| 3543 ++sortedNeighCellsIt, ++count) |
| 3544 { |
| 3545 uint16_t cellId = sortedNeighCellsIt->second; |
| 3546 std::map<uint16_t, NistMeasValues>::iterator neighborMeasIt = m_st
oredNistMeasValues.find (cellId); |
| 3547 NS_ASSERT (neighborMeasIt != m_storedNistMeasValues.end ()); |
| 3548 NistLteRrcSap::NistMeasResultEutra measResultEutra; |
| 3549 measResultEutra.physCellId = cellId; |
| 3550 measResultEutra.haveNistCgiInfo = false; |
| 3551 measResultEutra.haveRsrpResult = true; |
| 3552 measResultEutra.rsrpResult = NistEutranMeasurementMapping::Dbm2Rsr
pRange (neighborMeasIt->second.rsrp); |
| 3553 measResultEutra.haveRsrqResult = true; |
| 3554 measResultEutra.rsrqResult = NistEutranMeasurementMapping::Db2Rsrq
Range (neighborMeasIt->second.rsrq); |
| 3555 NS_LOG_INFO (this << " reporting neighbor cell " << (uint32_t) mea
sResultEutra.physCellId· |
| 3556 << " RSRP " << (uint32_t) measResultEutra.rsrpRe
sult |
| 3557 << " (" << neighborMeasIt->second.rsrp << " dBm)
" |
| 3558 << " RSRQ " << (uint32_t) measResultEutra.rsrqRe
sult |
| 3559 << " (" << neighborMeasIt->second.rsrq << " dB)"
); |
| 3560 measResults.measResultListEutra.push_back (measResultEutra); |
| 3561 measResults.haveMeasResultNeighCells = true; |
| 3562 } |
| 3563 } |
| 3564 else |
| 3565 { |
| 3566 NS_LOG_WARN (this << " cellsTriggeredList is empty"); |
| 3567 } |
| 3568 |
| 3569 /* |
| 3570 * The current NistLteRrcSap implementation is broken in that it does not |
| 3571 * allow for infinite values of reportAmount, which is probably the most |
| 3572 * reasonable setting. So we just always assume infinite reportAmount. |
| 3573 */ |
| 3574 measReportIt->second.numberOfReportsSent++; |
| 3575 measReportIt->second.periodicReportTimer.Cancel (); |
| 3576 |
| 3577 Time reportInterval; |
| 3578 switch (reportConfigEutra.reportInterval) |
| 3579 { |
| 3580 case NistLteRrcSap::NistReportConfigEutra::MS120: |
| 3581 reportInterval = MilliSeconds (120); |
| 3582 break; |
| 3583 case NistLteRrcSap::NistReportConfigEutra::MS240: |
| 3584 reportInterval = MilliSeconds (240); |
| 3585 break; |
| 3586 case NistLteRrcSap::NistReportConfigEutra::MS480: |
| 3587 reportInterval = MilliSeconds (480); |
| 3588 break; |
| 3589 case NistLteRrcSap::NistReportConfigEutra::MS640: |
| 3590 reportInterval = MilliSeconds (640); |
| 3591 break; |
| 3592 case NistLteRrcSap::NistReportConfigEutra::MS1024: |
| 3593 reportInterval = MilliSeconds (1024); |
| 3594 break; |
| 3595 case NistLteRrcSap::NistReportConfigEutra::MS2048: |
| 3596 reportInterval = MilliSeconds (2048); |
| 3597 break; |
| 3598 case NistLteRrcSap::NistReportConfigEutra::MS5120: |
| 3599 reportInterval = MilliSeconds (5120); |
| 3600 break; |
| 3601 case NistLteRrcSap::NistReportConfigEutra::MS10240: |
| 3602 reportInterval = MilliSeconds (10240); |
| 3603 break; |
| 3604 case NistLteRrcSap::NistReportConfigEutra::MIN1: |
| 3605 reportInterval = Seconds (60); |
| 3606 break; |
| 3607 case NistLteRrcSap::NistReportConfigEutra::MIN6: |
| 3608 reportInterval = Seconds (360); |
| 3609 break; |
| 3610 case NistLteRrcSap::NistReportConfigEutra::MIN12: |
| 3611 reportInterval = Seconds (720); |
| 3612 break; |
| 3613 case NistLteRrcSap::NistReportConfigEutra::MIN30: |
| 3614 reportInterval = Seconds (1800); |
| 3615 break; |
| 3616 case NistLteRrcSap::NistReportConfigEutra::MIN60: |
| 3617 reportInterval = Seconds (3600); |
| 3618 break; |
| 3619 default: |
| 3620 NS_FATAL_ERROR ("Unsupported reportInterval " << (uint16_t) reportConf
igEutra.reportInterval); |
| 3621 break; |
| 3622 } |
| 3623 |
| 3624 // schedule the next measurement reporting |
| 3625 measReportIt->second.periodicReportTimer· |
| 3626 = Simulator::Schedule (reportInterval, |
| 3627 &NistLteUeRrc::SendNistMeasurementReport, |
| 3628 this, measId); |
| 3629 |
| 3630 // send the measurement report to eNodeB |
| 3631 m_rrcSapUser->SendNistMeasurementReport (measurementReport); |
| 3632 }· |
| 3633 } |
| 3634 |
| 3635 void· |
| 3636 NistLteUeRrc::StartConnection () |
| 3637 { |
| 3638 NS_LOG_FUNCTION (this << m_imsi); |
| 3639 NS_ASSERT (m_hasReceivedMib); |
| 3640 NS_ASSERT (m_hasReceivedSib2); |
| 3641 m_connectionPending = false; // reset the flag |
| 3642 SwitchToState (IDLE_RANDOM_ACCESS); |
| 3643 m_cmacSapProvider->StartContentionBasedRandomAccessProcedure (); |
| 3644 } |
| 3645 |
| 3646 void· |
| 3647 NistLteUeRrc::LeaveConnectedMode () |
| 3648 { |
| 3649 NS_LOG_FUNCTION (this << m_imsi); |
| 3650 m_asSapUser->NotifyConnectionReleased (); |
| 3651 m_cmacSapProvider->RemoveLc (1); |
| 3652 std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it; |
| 3653 for (it = m_drbMap.begin (); it != m_drbMap.end (); ++it) |
| 3654 { |
| 3655 m_cmacSapProvider->RemoveLc (it->second->m_logicalChannelIdentity); |
| 3656 } |
| 3657 m_drbMap.clear (); |
| 3658 m_bid2DrbidMap.clear (); |
| 3659 m_srb1 = 0; |
| 3660 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 3661 } |
| 3662 |
| 3663 void |
| 3664 NistLteUeRrc::ConnectionTimeout () |
| 3665 { |
| 3666 NS_LOG_FUNCTION (this << m_imsi); |
| 3667 m_cmacSapProvider->Reset (); // reset the MAC |
| 3668 m_hasReceivedSib2 = false; // invalidate the previously received SIB2 |
| 3669 SwitchToState (IDLE_CAMPED_NORMALLY); |
| 3670 m_connectionTimeoutTrace (m_imsi, m_cellId, m_rnti); |
| 3671 m_asSapUser->NotifyConnectionFailed (); // inform upper layer |
| 3672 } |
| 3673 |
| 3674 void |
| 3675 NistLteUeRrc::DisposeOldSrb1 () |
| 3676 { |
| 3677 NS_LOG_FUNCTION (this); |
| 3678 m_srb1Old = 0; |
| 3679 } |
| 3680 |
| 3681 uint8_t· |
| 3682 NistLteUeRrc::Bid2Drbid (uint8_t bid) |
| 3683 { |
| 3684 std::map<uint8_t, uint8_t>::iterator it = m_bid2DrbidMap.find (bid); |
| 3685 //NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid); |
| 3686 if (it == m_bid2DrbidMap.end ()) |
| 3687 { |
| 3688 return 0; |
| 3689 } |
| 3690 else |
| 3691 { |
| 3692 return it->second; |
| 3693 } |
| 3694 } |
| 3695 |
| 3696 void· |
| 3697 NistLteUeRrc::SwitchToState (State newState) |
| 3698 { |
| 3699 NS_LOG_FUNCTION (this << ToString (newState)); |
| 3700 State oldState = m_state; |
| 3701 m_state = newState; |
| 3702 NS_LOG_INFO (this << " IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc " |
| 3703 << ToString (oldState) << " --> " << ToString (newState)); |
| 3704 m_stateTransitionTrace (m_imsi, m_cellId, m_rnti, oldState, newState); |
| 3705 |
| 3706 switch (newState) |
| 3707 { |
| 3708 case IDLE_START: |
| 3709 NS_FATAL_ERROR ("cannot switch to an initial state"); |
| 3710 break; |
| 3711 |
| 3712 case IDLE_CELL_SEARCH: |
| 3713 case IDLE_WAIT_MIB_SIB1: |
| 3714 case IDLE_WAIT_MIB: |
| 3715 case IDLE_WAIT_SIB1: |
| 3716 break; |
| 3717 |
| 3718 case IDLE_CAMPED_NORMALLY: |
| 3719 if (m_connectionPending) |
| 3720 { |
| 3721 SwitchToState (IDLE_WAIT_SIB2); |
| 3722 } |
| 3723 break; |
| 3724 |
| 3725 case IDLE_WAIT_SIB2: |
| 3726 if (m_hasReceivedSib2) |
| 3727 { |
| 3728 NS_ASSERT (m_connectionPending); |
| 3729 StartConnection (); |
| 3730 } |
| 3731 break; |
| 3732 |
| 3733 case IDLE_RANDOM_ACCESS: |
| 3734 case IDLE_CONNECTING: |
| 3735 case CONNECTED_NORMALLY: |
| 3736 case CONNECTED_HANDOVER: |
| 3737 case CONNECTED_PHY_PROBLEM: |
| 3738 case CONNECTED_REESTABLISHING: |
| 3739 break; |
| 3740 · |
| 3741 default: |
| 3742 break; |
| 3743 } |
| 3744 } |
| 3745 |
| 3746 /** |
| 3747 * Process dedicated sidelink configuration |
| 3748 * \param config The sidelink configuration |
| 3749 */ |
| 3750 void |
| 3751 NistLteUeRrc::ApplySidelinkDedicatedConfiguration (NistLteRrcSap::SlCommConfig c
onfig) |
| 3752 { |
| 3753 NS_LOG_FUNCTION (this); |
| 3754 |
| 3755 //TODO: implement procedures described in 5.3.10.X |
| 3756 // 1> if the RRCConnectionReconfiguration message includes the sl-CommConfig: |
| 3757 // 2> if commTxResources is included and set to setup: |
| 3758 // 3> from the next SC period use the resources indicated by commTxRes
ources for sidelink direct communication transmission, as specified in 5.X.4; |
| 3759 // 2> else if commTxResources is included and set to release: |
| 3760 // 3> from the next SC period, release the resources allocated for sid
elink direct communication transmission previously configured by commTxResources
; |
| 3761 |
| 3762 //pools are allocated per UE, not per destinations. A UE may have multiple poo
ls |
| 3763 //and we need to maintain the list of pools |
| 3764 //pass information to MAC to change scheduling |
| 3765 if (config.commTxResources == NistLteRrcSap::SlCommConfig::SETUP) { |
| 3766 NS_LOG_INFO ("Received dedicated resources " << config.setup.setup); |
| 3767 |
| 3768 Ptr<SidelinkTxCommResourcePool> txPool = CreateObject<SidelinkTxCommResource
Pool>(); |
| 3769 if (config.setup.setup == NistLteRrcSap::SlCommTxResourcesSetup::SCHEDULED)
{ |
| 3770 txPool->SetPool (config.setup.scheduled.commTxConfig); |
| 3771 txPool->SetScheduledTxParameters (config.setup.scheduled.crnti, config.set
up.scheduled.macMainConfig, config.setup.scheduled.commTxConfig, 0, config.setup
.scheduled.mcs); |
| 3772 } else { |
| 3773 NS_ASSERT (config.setup.ueSelected.havePoolToAdd); |
| 3774 //configure lower layers to transmit the sidelink control information and
the corresponding data using the pool of resources indicated by the first entry
in commTxPoolNormalDedicated; |
| 3775 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[0].pool); |
| 3776 } |
| 3777 ···· |
| 3778 std::list <uint32_t>::iterator it; |
| 3779 std::list <uint32_t> destinations = m_sidelinkConfiguration->GetTxDestinatio
ns (); |
| 3780 //int index = 0; |
| 3781 //currently we can only use one pool so all groups will use the same one |
| 3782 for (it = destinations.begin() ; it != destinations.end() ; it++) { |
| 3783 m_cmacSapProvider->AddSlTxPool (*it, txPool); |
| 3784 } |
| 3785 //inform PHY about pool |
| 3786 m_cphySapProvider->SetSlTxPool (txPool); |
| 3787 ···· |
| 3788 //indicate NAS that bearer was established |
| 3789 //TODO: we should only indicate this once per bearer |
| 3790 for (std::list <uint32_t>::iterator it = destinations.begin() ; it != destin
ations.end() ; it++) { |
| 3791 m_asSapUser->NotifySidelinkRadioBearerActivated (*it); |
| 3792 } |
| 3793 ···· |
| 3794 } else { |
| 3795 //release all tranmission pools |
| 3796 m_cphySapProvider->RemoveSlTxPool (); |
| 3797 } |
| 3798 |
| 3799 } |
| 3800 |
| 3801 void |
| 3802 NistLteUeRrc::ApplySidelinkDedicatedConfiguration (NistLteRrcSap::SlDiscConfig c
onfig) |
| 3803 { |
| 3804 NS_LOG_FUNCTION (this); |
| 3805 if (config.discTxResources == NistLteRrcSap::SlDiscConfig::SETUP) { |
| 3806 NS_LOG_INFO ("Received dedicated resources (discovery) " << config.setup.set
up); |
| 3807 |
| 3808 Ptr<SidelinkTxDiscResourcePool> txPool = CreateObject<SidelinkTxDiscResource
Pool>(); |
| 3809 |
| 3810 if (config.setup.setup == NistLteRrcSap::SlDiscTxResourcesSetup::SCHEDULED)
{ |
| 3811 txPool->SetPool (config.setup.scheduled.discTxConfig); |
| 3812 txPool->SetScheduledTxParameters (config.setup.scheduled.discTxConfig, con
fig.setup.scheduled.discTfIndexList, config.setup.scheduled.discHoppingConfigDis
c); |
| 3813 }· |
| 3814 else { |
| 3815 NS_ASSERT (config.setup.ueSelected.havePoolToAdd && config.setup.ueSelecte
d.poolToAddModList.nbPools > 0); |
| 3816 |
| 3817 // all pools in the same list have the same criteria for poolSelection |
| 3818 if (config.setup.ueSelected.poolToAddModList.pools[0].pool.txParameters.ue
SelectedResourceConfig.poolSelection.selection == NistLteRrcSap::PoolSelection::
RSRPBASED) { |
| 3819 |
| 3820 uint8_t i = 0; |
| 3821 bool poolFound = false; |
| 3822 while ((i < config.setup.ueSelected.poolToAddModList.nbPools) and (!pool
Found)) { |
| 3823 |
| 3824 // retrieve upper and lower RSRP bounds |
| 3825 // make sure that the current rsrp vlaue is in-between threshLow and t
hreshHigh; |
| 3826 // otherwise go to the next pool |
| 3827 uint32_t lowRsrp = config.setup.ueSelected.poolToAddModList.pools[i].p
ool.txParameters.ueSelectedResourceConfig.poolSelectionRsrpBased.threshLow; |
| 3828 uint32_t highRsrp = config.setup.ueSelected.poolToAddModList.pools[i].
pool.txParameters.ueSelectedResourceConfig.poolSelectionRsrpBased.threshHigh; |
| 3829 |
| 3830 // check the rsrp values : Value 0 corresponds to -infinity, value 1 t
o -110dBm,· |
| 3831 // value 2 to -100dBm, and so on (i.e. in steps of 10dBm) until value
6,· |
| 3832 // which corresponds to -60dBm, while value 7 corresponds to +infinity
. |
| 3833 NS_ASSERT_MSG (lowRsrp <= highRsrp, "Invalid Rsrp limits : lower bound
is greater than upper bound"); |
| 3834 NS_ASSERT_MSG ((lowRsrp != 7) and (highRsrp != 0), "invalid RSRP limit
s values"); |
| 3835 |
| 3836 // apply the layer 3 filter before checking the pool |
| 3837 SaveNistUeMeasurements (m_cellId, m_storedNistMeasValues[m_cellId].rsr
p, m_storedNistMeasValues[m_cellId].rsrq, true); |
| 3838 |
| 3839 //low = -infinity |
| 3840 if (lowRsrp == 0) { |
| 3841 //high = + infinity |
| 3842 if (highRsrp == 7) { |
| 3843 // any rsrp value would be ok : select first pool |
| 3844 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[0]
.pool); |
| 3845 poolFound = true; |
| 3846 } |
| 3847 //high could be : -110 dBm to -60 dBm· |
| 3848 else { |
| 3849 // check if rsrp <= highRsrp |
| 3850 if (m_storedNistMeasValues[m_cellId].rsrp <= NistLteRrcSap::RsrpVa
lueDbm (highRsrp)) { |
| 3851 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[
i].pool); |
| 3852 poolFound = true; |
| 3853 } |
| 3854 } |
| 3855 } |
| 3856 // low could be : -110 dBm to -60 dBm· |
| 3857 else { |
| 3858 //high = + infinity |
| 3859 if (highRsrp == 7) { |
| 3860 // check if rsrp >= lowRsrp |
| 3861 if (m_storedNistMeasValues[m_cellId].rsrp >= NistLteRrcSap::RsrpVa
lueDbm (lowRsrp)) { |
| 3862 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[
i].pool); |
| 3863 poolFound = true; |
| 3864 } |
| 3865 } |
| 3866 //high could be : -110 dBm to -60 dBm |
| 3867 else { |
| 3868 // check if lowRsrp <= rsrp <= highRsrp |
| 3869 if (((m_storedNistMeasValues[m_cellId].rsrp >= NistLteRrcSap::Rsrp
ValueDbm (lowRsrp)) and (m_storedNistMeasValues[m_cellId].rsrp <= NistLteRrcSap:
:RsrpValueDbm (highRsrp)))) { |
| 3870 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[
i].pool); |
| 3871 poolFound = true; |
| 3872 } |
| 3873 } |
| 3874 }········· |
| 3875 //increment; so if the pool is not good, go to the next one |
| 3876 i++; |
| 3877 }//end while |
| 3878 NS_ASSERT_MSG (poolFound, "No pool match the RSRP-based selection"); |
| 3879 }//end if (rsrp) |
| 3880 |
| 3881 else { |
| 3882 // ue selected : randomly selected using a uniform distribution |
| 3883 txPool->SetPool (config.setup.ueSelected.poolToAddModList.pools[m_sidelink
Configuration->m_rand->GetInteger (0, config.setup.ueSelected.poolToAddModList.n
bPools - 1)].pool); |
| 3884 } |
| 3885 }//end if (ue selected) |
| 3886 ········ |
| 3887 //inform MAC about the pool |
| 3888 m_cmacSapProvider->AddSlTxPool (txPool); |
| 3889 //inform PHY about the pool |
| 3890 m_cphySapProvider->SetSlTxPool (txPool);· |
| 3891 |
| 3892 }//end if (setup) |
| 3893 |
| 3894 else { |
| 3895 //release all tranmission pools |
| 3896 m_cphySapProvider->RemoveSlTxPool (true); // add bool value so that we can u
se the function for discovery |
| 3897 } |
| 3898 } |
| 3899 |
| 3900 |
| 3901 |
| 3902 /** |
| 3903 * Transmits a SidelinkUEInformation message to the eNodeB |
| 3904 */ |
| 3905 void |
| 3906 NistLteUeRrc::SendSidelinkUeInformation () |
| 3907 { |
| 3908 NS_LOG_FUNCTION (this); |
| 3909 |
| 3910 NistLteRrcSap::SidelinkUeInformation sidelinkUeInformation; |
| 3911 sidelinkUeInformation.haveCommRxInterestedFreq = false; |
| 3912 sidelinkUeInformation.haveCommTxResourceReq = false; |
| 3913 sidelinkUeInformation.haveDiscRxInterest = false;· |
| 3914 sidelinkUeInformation.haveDiscTxResourceReq = false;· |
| 3915 |
| 3916 std::map <uint16_t, LteUeRrcSl::LteSlCellConfiguration>::iterator it = m_sidel
inkConfiguration->m_slMap.find (m_cellId); |
| 3917 if (it != m_sidelinkConfiguration->m_slMap.end ()) { |
| 3918 //if SIB 18 received |
| 3919 // if configured to receive sidelink communication |
| 3920 // set commRxInterestedFreq with sidelink frequency |
| 3921 ···· |
| 3922 // if configuration to transmit sidelink communication |
| 3923 // set commTxResourceReq with sidelink frequency and list of destination |
| 3924 if (it->second.haveSib18) { |
| 3925 if (m_sidelinkConfiguration->IsRxInterested ()) { |
| 3926 sidelinkUeInformation.haveCommRxInterestedFreq = true; |
| 3927 sidelinkUeInformation.commRxInterestedFreq = GetUlEarfcn (); |
| 3928 } |
| 3929 if (m_sidelinkConfiguration->IsTxInterested ()) { |
| 3930 std::list <uint32_t> destinations = m_sidelinkConfiguration->GetTxDestin
ations (); |
| 3931 sidelinkUeInformation.haveCommTxResourceReq = true; |
| 3932 sidelinkUeInformation.slCommTxResourceReq.carrierFreq = GetUlEarfcn (); |
| 3933 sidelinkUeInformation.slCommTxResourceReq.slDestinationInfoList.nbDestin
ations = destinations.size (); |
| 3934 std::list <uint32_t>::iterator it; |
| 3935 int index = 0; |
| 3936 for (it = destinations.begin() ; it != destinations.end() ; it++) { |
| 3937 sidelinkUeInformation.slCommTxResourceReq.slDestinationInfoList.SlDest
inationIdentity[index++] = *it; |
| 3938 } |
| 3939 } |
| 3940 }························· |
| 3941 |
| 3942 // similar for SIB 19 |
| 3943 if (it->second.haveSib19) { |
| 3944 |
| 3945 // UE interested in monitoring discovery announcements |
| 3946 if ((m_sidelinkConfiguration->IsMonitoringInterested ()) and (m_sidelinkC
onfiguration->GetDiscInterFreq () == GetUlEarfcn ()))· |
| 3947 { |
| 3948 sidelinkUeInformation.haveDiscRxInterest = true; |
| 3949 sidelinkUeInformation.discRxInterest = true; |
| 3950 } |
| 3951 // UE interested in transmit discovery announcements |
| 3952 if (m_sidelinkConfiguration->IsAnnouncingInterested ()) {········ |
| 3953 sidelinkUeInformation.haveDiscTxResourceReq = true;······ |
| 3954 NS_ASSERT_MSG (m_sidelinkConfiguration->GetDiscTxResources ()>0, "can't
have 0 or negative resources for the discovery announcement. Check if DiscTxReso
urces is defined for in-coverage or eNBs disabled for ou-of-coverage"); |
| 3955 sidelinkUeInformation.discTxResourceReq = m_sidelinkConfiguration->GetDi
scTxResources (); |
| 3956 } |
| 3957 } |
| 3958 |
| 3959 // Record time |
| 3960 m_sidelinkConfiguration->RecordTransmissionOfSidelinkUeInformation (); |
| 3961 // send the message to eNodeB |
| 3962 m_rrcSapUser->SendSidelinkUeInformation (sidelinkUeInformation); |
| 3963 } |
| 3964 }· |
| 3965 |
| 3966 void NistLteUeRrc::DoNotifySidelinkReception (uint8_t lcId, uint32_t srcL2Id, ui
nt32_t dstL2Id) |
| 3967 { |
| 3968 NS_LOG_FUNCTION (this << (uint16_t)lcId << srcL2Id << dstL2Id); |
| 3969 |
| 3970 //add LC |
| 3971 Ptr<LteSidelinkRadioBearerInfo> slbInfo = AddSlrb (srcL2Id, dstL2Id, lcId); |
| 3972 NS_LOG_INFO ("Created new RX SLRB for group " << dstL2Id << " LCID=" << (slbIn
fo->m_logicalChannelIdentity & 0xF)); |
| 3973 } |
| 3974 |
| 3975 void NistLteUeRrc::DoNotifyDiscoveryReception (Ptr<NistLteControlMessage> msg) |
| 3976 { |
| 3977 NS_LOG_FUNCTION (this << msg); |
| 3978 Ptr<NistSlDiscMessage> msg2 = DynamicCast<NistSlDiscMessage> (msg); |
| 3979 NistSlDiscMsg disc = msg2->GetSlDiscMessage (); |
| 3980 for (std::list<uint32_t>::iterator it = m_sidelinkConfiguration->m_monitorApps
.begin (); it != m_sidelinkConfiguration->m_monitorApps.end (); ++it) |
| 3981 { |
| 3982 if ((std::bitset <184>)*it == disc.m_proSeAppCode) |
| 3983 { |
| 3984 NS_LOG_INFO ("discovery message received by " << m_rnti << ", proSeAppCode
= " << *it); |
| 3985 m_discoveryMonitoringTrace (m_imsi, m_cellId, m_rnti, *it); |
| 3986 } |
| 3987 } |
| 3988 } |
| 3989 |
| 3990 void |
| 3991 NistLteUeRrc::SetSlssid(uint64_t slssid){ |
| 3992 NS_LOG_FUNCTION (this << slssid); |
| 3993 m_slssId = slssid; |
| 3994 //Pass it to lower layers as well |
| 3995 m_cphySapProvider->SetSlssId(slssid); |
| 3996 } |
| 3997 |
| 3998 uint64_t |
| 3999 NistLteUeRrc::GetSlssid() |
| 4000 { |
| 4001 NS_LOG_FUNCTION (this); |
| 4002 return m_slssId; |
| 4003 } |
| 4004 |
| 4005 uint64_t |
| 4006 NistLteUeRrc::GetFrameNumber() |
| 4007 { |
| 4008 NS_LOG_FUNCTION (this); |
| 4009 return m_currFrameNo; |
| 4010 } |
| 4011 |
| 4012 uint64_t |
| 4013 NistLteUeRrc::GetSubFrameNumber() |
| 4014 { |
| 4015 NS_LOG_FUNCTION (this); |
| 4016 return m_currSubframeNo; |
| 4017 } |
| 4018 |
| 4019 void |
| 4020 NistLteUeRrc::InitiateSlssTransmission() |
| 4021 { |
| 4022 NS_LOG_FUNCTION (this); |
| 4023 |
| 4024 //Try to initiate SLSS transmissions only once ending an off-data period (didn
't have data to transmit before) |
| 4025 if (!m_hasDataToTransmit) |
| 4026 { |
| 4027 NS_LOG_LOGIC (this << " the UE has data to transmit"); |
| 4028 m_hasDataToTransmit = true; |
| 4029 if (m_hasSyncRef && IsInTheInnerPartOfTheSyncRefCell(m_currSyncRef.slssid,
m_currSyncRef.rxOffset)) |
| 4030 { |
| 4031 m_inInnerCellOfSyncRef = true; |
| 4032 NS_LOG_LOGIC (this << " the UE is in the inner cell of the selected Sy
ncRef, no SLSS transmissions initiated"); |
| 4033 } |
| 4034 else |
| 4035 { |
| 4036 NS_LOG_LOGIC (this << " the UE is in the outer cell of the selected Sy
ncRef, SLSS transmissions initiated"); |
| 4037 ActivateSlssTransmission(); |
| 4038 } |
| 4039 } |
| 4040 } |
| 4041 |
| 4042 void |
| 4043 NistLteUeRrc::StopSlssTransmission() |
| 4044 { |
| 4045 NS_LOG_FUNCTION (this); |
| 4046 |
| 4047 //Try to stop SLSS transmissions only once ending an on-data period (had data
to transmit before) |
| 4048 if(m_hasDataToTransmit) |
| 4049 { |
| 4050 m_hasDataToTransmit = false; |
| 4051 NS_LOG_LOGIC (this << " the UE has no data to transmit, stopping SLSS tran
smission"); |
| 4052 DeactivateSlssTransmission(); |
| 4053 } |
| 4054 } |
| 4055 |
| 4056 void NistLteUeRrc::ActivateSlssTransmission () |
| 4057 { |
| 4058 NS_LOG_FUNCTION (this); |
| 4059 |
| 4060 if (!m_slssTransmissionActive) |
| 4061 { |
| 4062 NS_LOG_LOGIC (this << " the SLSS transmission was not active, configuring
it and activating it"); |
| 4063 m_slssTransmissionActive = true; |
| 4064 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->GetSl
Preconfiguration (); |
| 4065 //Configure own SLSSID and SyncOffsetIndicator |
| 4066 if(m_hasSyncRef || m_currSyncRef.slssid != 0) |
| 4067 { |
| 4068 NS_LOG_LOGIC (this << " the UE has a selected SyncRef, using its SLSSI
D and the other offset indicator"); |
| 4069 //Use the values from the SyncRef |
| 4070 m_slssId = m_currSyncRef.slssid; |
| 4071 uint16_t currSyncRefSyncOffsetIndicator = (10*m_currSyncRef.directFram
eNo + m_currSyncRef.directSubframeNo) % 40; |
| 4072 if(currSyncRefSyncOffsetIndicator == preconf.preconfigSync.syncOffsetI
ndicator1 ) |
| 4073 { |
| 4074 m_txSlSyncOffsetIndicator = preconf.preconfigSync.syncOffsetIndica
tor2; |
| 4075 } else{ |
| 4076 m_txSlSyncOffsetIndicator = preconf.preconfigSync.syncOffsetIndi
cator1; |
| 4077 } |
| 4078 } |
| 4079 else |
| 4080 { |
| 4081 NS_LOG_LOGIC (this << " the UE does not have a selected SyncRef, selec
ting SLSSID and offset indicator randomly"); |
| 4082 //Choose SLSSID Randomly between 168 and 335 |
| 4083 SlChangeOfSyncRefStatParameters param; |
| 4084 |
| 4085 param.imsi=m_imsi; |
| 4086 param.prevSlssid =m_slssId; |
| 4087 param.prevRxOffset=0; |
| 4088 param.prevFrameNo=m_currFrameNo; |
| 4089 param.prevSubframeNo=m_currSubframeNo; |
| 4090 |
| 4091 m_slssId= m_imsi*10; |
| 4092 |
| 4093 param.currSlssid=m_slssId; |
| 4094 param.currRxOffset=0; |
| 4095 param.currFrameNo=m_currFrameNo; |
| 4096 param.currSubframeNo=m_currSubframeNo; |
| 4097 |
| 4098 m_ChangeOfSyncRefTrace(param); |
| 4099 |
| 4100 //Choose SyncOffsetIndicator randomly between the two preconfigured va
lues |
| 4101 Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> (); |
| 4102 if(x->GetInteger(0,1)) |
| 4103 { |
| 4104 m_txSlSyncOffsetIndicator = preconf.preconfigSync.syncOffsetIndica
tor1; |
| 4105 } |
| 4106 else |
| 4107 { |
| 4108 m_txSlSyncOffsetIndicator = preconf.preconfigSync.syncOffsetIndica
tor2; |
| 4109 } |
| 4110 } |
| 4111 //Schedule the sending of the first MIB-SL according the selected SyncOffs
etIndicator |
| 4112 uint16_t nextSLSS=0; |
| 4113 uint16_t currOffset = (m_currFrameNo*10 + m_currSubframeNo) % 40 ; |
| 4114 if ( currOffset < m_txSlSyncOffsetIndicator) |
| 4115 { |
| 4116 nextSLSS = m_txSlSyncOffsetIndicator - currOffset; |
| 4117 } |
| 4118 else |
| 4119 { |
| 4120 nextSLSS = 40 - currOffset + m_txSlSyncOffsetIndicator; |
| 4121 } |
| 4122 NS_LOG_INFO (this << " UE IMSI "<<m_imsi <<" activating SLSS transmission
with SLSSID " << m_slssId <<", first SLSS in "<< nextSLSS<< "ms"); |
| 4123 |
| 4124 |
| 4125 Simulator::Schedule (MilliSeconds(nextSLSS), &NistLteUeRrc::SendSlss, this
); |
| 4126 m_slssTxTime = MilliSeconds(Simulator::Now().GetMilliSeconds()+nextSLSS); |
| 4127 } |
| 4128 } |
| 4129 |
| 4130 void NistLteUeRrc::DeactivateSlssTransmission () |
| 4131 { |
| 4132 NS_LOG_FUNCTION (this); |
| 4133 |
| 4134 if (m_slssTransmissionActive) |
| 4135 { |
| 4136 m_slssTransmissionActive = false; |
| 4137 } |
| 4138 } |
| 4139 |
| 4140 void NistLteUeRrc::SaveSubframeIndication(uint16_t frameNo, uint16_t subFrameNo) |
| 4141 { |
| 4142 //NS_LOG_FUNCTION (this << frameNo << subFrameNo ); //To much overhead as it i
s called every ms |
| 4143 m_currFrameNo = frameNo; |
| 4144 m_currSubframeNo = subFrameNo; |
| 4145 } |
| 4146 |
| 4147 void |
| 4148 NistLteUeRrc::SendSlss(){ |
| 4149 |
| 4150 NS_LOG_FUNCTION (this); |
| 4151 |
| 4152 if(m_slssTransmissionActive) |
| 4153 { |
| 4154 NS_LOG_LOGIC (this << " the SLSS transmission is active"); |
| 4155 //Send a SLSS if the UE is supposed to send it now (e.g. it didn't change
of timing/SyncRef) |
| 4156 if((m_currFrameNo*10 + m_currSubframeNo) % 40 == m_txSlSyncOffsetIndicator
) |
| 4157 { |
| 4158 NS_LOG_LOGIC (this << " the UE is supposed to send the SLSS now"); |
| 4159 |
| 4160 NistLteRrcSap::MasterInformationBlockSL mibSl; |
| 4161 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->G
etSlPreconfiguration (); |
| 4162 |
| 4163 mibSl.slBandwidth = preconf.preconfigGeneral.slBandwidth; |
| 4164 mibSl.inCoverage = m_inCoverage; |
| 4165 mibSl.directFrameNo = m_currFrameNo; |
| 4166 mibSl.directSubframeNo = m_currSubframeNo ; |
| 4167 mibSl.creationTimestamp = Simulator::Now(); |
| 4168 |
| 4169 if(!m_hasSyncRef) |
| 4170 { |
| 4171 mibSl.slssid = m_slssId; |
| 4172 } |
| 4173 else |
| 4174 { |
| 4175 mibSl.slssid = m_currSyncRef.slssid; |
| 4176 } |
| 4177 |
| 4178 //Send the SLSS |
| 4179 NS_LOG_INFO (this <<" UE IMSI "<<m_imsi <<" sending SLSS"); |
| 4180 NS_LOG_INFO (this << " mibSl.slBandwidth "<<mibSl.slBandwidth |
| 4181 <<" mibSl.inCoverage "<<mibSl.inCoverage |
| 4182 <<" mibSl.directFrameNo "<<mibSl.directFrameNo |
| 4183 <<" mibSl.directSubframeNo "<<mibSl.directSubframeNo |
| 4184 <<" mibSl.slssid "<<mibSl.slssid); |
| 4185 |
| 4186 m_SendSlssTrace(m_imsi,mibSl.slssid,m_txSlSyncOffsetIndicator,mibSl.in
Coverage,mibSl.directFrameNo,mibSl.directSubframeNo); |
| 4187 |
| 4188 m_cphySapProvider->SendSlss(mibSl); |
| 4189 } |
| 4190 |
| 4191 //Calculate when the next SLSS is supposed to be send |
| 4192 uint16_t nextSLSS=0; |
| 4193 uint16_t currOffset = (m_currFrameNo*10 + m_currSubframeNo) % 40 ; |
| 4194 if ( currOffset < m_txSlSyncOffsetIndicator) |
| 4195 { |
| 4196 nextSLSS = m_txSlSyncOffsetIndicator - currOffset; |
| 4197 } |
| 4198 else |
| 4199 { |
| 4200 nextSLSS = 40 - currOffset + m_txSlSyncOffsetIndicator; |
| 4201 } |
| 4202 |
| 4203 //Schedule the sent of the SLSS if it wasn't scheduled already |
| 4204 if (m_slssTxTime.GetMilliSeconds() == Simulator::Now().GetMilliSeconds()) |
| 4205 { |
| 4206 Simulator::Schedule (MilliSeconds(nextSLSS), &NistLteUeRrc::SendSlss,
this); |
| 4207 m_slssTxTime = MilliSeconds(Simulator::Now().GetMilliSeconds()+nextSLS
S); |
| 4208 NS_LOG_LOGIC (this << " UE IMSI "<<m_imsi <<" scheduled a SLSS to be s
ent in "<<nextSLSS<<" ms"); |
| 4209 } |
| 4210 else |
| 4211 { |
| 4212 NS_LOG_LOGIC (this << " UE IMSI "<<m_imsi <<" Duplicated SLSS scheduli
ng, ignoring"); |
| 4213 } |
| 4214 } |
| 4215 } |
| 4216 |
| 4217 void |
| 4218 NistLteUeRrc::SaveSlssMeasurements (uint16_t slssid, uint16_t offset, double srs
rp, bool useLayer3Filtering) |
| 4219 { |
| 4220 NS_LOG_FUNCTION (this << slssid << offset << srsrp << useLayer3Filtering); |
| 4221 |
| 4222 std::map <std::pair<uint16_t,uint16_t>, SlssMeasValues>::iterator storedMeasIt
= m_storedSlssMeasValues.find (std::pair<uint16_t,uint16_t>(slssid,offset)); |
| 4223 |
| 4224 if (storedMeasIt != m_storedSlssMeasValues.end ()) |
| 4225 { |
| 4226 NS_LOG_LOGIC (this << " This SyncRef was measured in the past"); |
| 4227 |
| 4228 if (useLayer3Filtering) |
| 4229 { |
| 4230 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->G
etSlPreconfiguration (); |
| 4231 NS_LOG_LOGIC (this << " Using L3 filtering with preconfigured filterCo
efficient: "<< preconf.preconfigSync.filterCoefficient); |
| 4232 |
| 4233 bool valid = false; |
| 4234 |
| 4235 //Converting stored S-RSRP to linear units |
| 4236 double storedSrsrp_W = std::pow(10.0,storedMeasIt->second.srsrp/10.0)/
1000.0; |
| 4237 |
| 4238 double Fn_W; |
| 4239 if (srsrp > m_minSrsrp) |
| 4240 { |
| 4241 NS_LOG_LOGIC (this << " The new SyncRef S-RSRP is above the minimu
m required, applying filter"); |
| 4242 |
| 4243 double newSrsrp_W = std::pow(10.0,srsrp/10.0)/1000.0; |
| 4244 |
| 4245 //The filter to be used according to //TS 36.331 5.5.3.2 is |
| 4246 // F_n = (1-a)*F_{n-1} + a*M_n |
| 4247 //and it is defined for an input rate of 200 ms. |
| 4248 //If the input rate is different, the filter needs to be adapted s
uch that |
| 4249 //its time characteristics are preserved. |
| 4250 //This is achieved using: |
| 4251 // F_n = (1-a)^(nP) F_{n-1} + a M_n |
| 4252 //where nP is the number of 200 ms periods that have elapsed since
last time |
| 4253 //the quantity was filtered and stored |
| 4254 |
| 4255 double aSrsrp = std::pow (0.5, preconf.preconfigSync.filterCoeffic
ient / 4.0); //TS 36.331 5.5.3.2 is |
| 4256 double nP = (Simulator::Now().GetMilliSeconds() - storedMeasIt->s
econd.timestamp.GetMilliSeconds()) / 200; |
| 4257 //std::cout<< Simulator::Now().GetMilliSeconds()<<" imsi: "<<m_ims
i<< " slssid: "<< slssid << " offset: "<<offset <<" srsrp: "<< srsrp<< |
| 4258 // "timestamp: "<<storedMeasIt->second.timestamp.GetMilliSecond
s()<< std::endl; |
| 4259 Fn_W = std::pow ((1 - aSrsrp),nP) * storedSrsrp_W + aSrsrp * newSr
srp_W; |
| 4260 valid=true; |
| 4261 } |
| 4262 else |
| 4263 { |
| 4264 NS_LOG_LOGIC (this << " The new SyncRef S-RSRP is below or equal t
o the minimum required... Ignoring measurement"); |
| 4265 } |
| 4266 |
| 4267 if (valid) |
| 4268 { |
| 4269 //Converting filtered value to dBm |
| 4270 double Fn_dBm = 10 * log10 (1000 * (Fn_W)); |
| 4271 |
| 4272 //If after the filtering, it decays below the minimum required, use
the minimum required |
| 4273 if(Fn_dBm <= m_minSrsrp) |
| 4274 { |
| 4275 NS_LOG_LOGIC (this << " The L3 filtered SyncRef S-RSRP is below
or equal to the minimum required, storing minimum required"); |
| 4276 storedMeasIt->second.srsrp = m_minSrsrp; |
| 4277 storedMeasIt->second.timestamp = Simulator::Now (); |
| 4278 } |
| 4279 else |
| 4280 { |
| 4281 NS_LOG_LOGIC (this << " The L3 filtered SyncRef S-RSRP is above
the minimum required, storing it"); |
| 4282 storedMeasIt->second.srsrp = Fn_dBm; |
| 4283 storedMeasIt->second.timestamp = Simulator::Now (); |
| 4284 } |
| 4285 } |
| 4286 } |
| 4287 else |
| 4288 { |
| 4289 NS_LOG_LOGIC (this << " Not using L3 filtering"); |
| 4290 storedMeasIt->second.srsrp = srsrp; |
| 4291 storedMeasIt->second.timestamp = Simulator::Now (); |
| 4292 } |
| 4293 } |
| 4294 else |
| 4295 { |
| 4296 NS_LOG_LOGIC (this << " First time measuring this SyncRef, storing first v
alue"); |
| 4297 SlssMeasValues v; |
| 4298 v.srsrp = srsrp; |
| 4299 v.timestamp = Simulator::Now (); |
| 4300 m_storedSlssMeasValues.insert(std::pair< std::pair<uint16_t,uint16_t>, Sls
sMeasValues>(std::pair<uint16_t,uint16_t>(slssid,offset), v)); |
| 4301 m_knownSlssidList.push_back(std::pair<uint16_t,uint16_t>(slssid,offset)); |
| 4302 } |
| 4303 NS_LOG_INFO (this <<" IMSI " << m_imsi << " measured SyncRef with slssid " <<
slssid << " and offset " << offset <<" New S-RSRP " |
| 4304 << srsrp << " Stored S-RSRP " << storedMeasIt->second.srsrp); |
| 4305 } |
| 4306 |
| 4307 void |
| 4308 NistLteUeRrc::SynchronizeToStrongestSyncRef () |
| 4309 { |
| 4310 NS_LOG_FUNCTION (this); |
| 4311 |
| 4312 uint64_t maxSrsrpSlssid = 0; |
| 4313 uint64_t maxSrsrpOffset = 0; |
| 4314 |
| 4315 double maxSrsrp = -std::numeric_limits<double>::infinity (); |
| 4316 |
| 4317 //Determine the strongest SyncRef |
| 4318 std::vector <std::pair<uint16_t,uint16_t> >::iterator RepIt; |
| 4319 for (RepIt = m_lastReportedSlssidList.begin (); RepIt != m_lastReportedSlssidL
ist.end (); ++RepIt) |
| 4320 { |
| 4321 std::map <std::pair<uint16_t,uint16_t>, SlssMeasValues>::iterator it = m_s
toredSlssMeasValues.find(std::pair<uint16_t,uint16_t>(*RepIt)); |
| 4322 if (it == m_storedSlssMeasValues.end ()) |
| 4323 { |
| 4324 NS_LOG_ERROR(" The UE cannot find the S-RSRP measurements for the dete
cted SyncRef SLSSID " << RepIt->first <<" offset " <<RepIt->second ); |
| 4325 } |
| 4326 else |
| 4327 { |
| 4328 if (maxSrsrp < it->second.srsrp) |
| 4329 { |
| 4330 maxSrsrpSlssid = it->first.first ; |
| 4331 maxSrsrpOffset = it->first.second; |
| 4332 maxSrsrp = it->second.srsrp; |
| 4333 } |
| 4334 } |
| 4335 } |
| 4336 |
| 4337 NS_LOG_INFO (this <<" The strongest SyncRef SLSSID "<< maxSrsrpSlssid << " off
set "<<maxSrsrpOffset <<" has a S-RSRP of "<<maxSrsrp<<" dBm" ); |
| 4338 |
| 4339 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->GetSlPrec
onfiguration (); |
| 4340 |
| 4341 if (maxSrsrpSlssid == 0 || maxSrsrp - m_minSrsrp < preconf.preconfigSync.sync
RefMinHyst) |
| 4342 { |
| 4343 NS_LOG_LOGIC (this << " Unable to find suitable SyncRef"); |
| 4344 if(!m_slssTransmissionActive && m_hasDataToTransmit) |
| 4345 { |
| 4346 NS_LOG_LOGIC (this <<" The UE is transmitting sidelink communication..
. Activating own SLSS transmission"); |
| 4347 ActivateSlssTransmission(); |
| 4348 } |
| 4349 } |
| 4350 else |
| 4351 { |
| 4352 NS_LOG_LOGIC (this << " The strongest SyncRef is suitable"); |
| 4353 |
| 4354 //Verify we have the mib for the strongest SyncRef |
| 4355 std::map <std::pair<uint16_t,uint16_t>, NistLteRrcSap::MasterInformationBl
ockSL>::iterator itMap |
| 4356 = m_latestMibSlReceived.find (std::pair<uint16_t,uint16_t>(maxSrsrpSlssid,
maxSrsrpOffset )); |
| 4357 if (itMap == m_latestMibSlReceived.end ()) |
| 4358 { |
| 4359 NS_LOG_ERROR(" The UE is unable to find the MIB-SL of the strongest Sy
ncRef"); |
| 4360 } |
| 4361 else |
| 4362 { |
| 4363 NS_LOG_LOGIC (this << " The MIB-SL of the strongest SyncRef was found.
.. Instructing synchronization"); |
| 4364 |
| 4365 NS_LOG_INFO (this <<" UE IMSI "<<m_imsi <<" selected SyncRef slssid "<
<maxSrsrpSlssid << " offset " << maxSrsrpOffset); |
| 4366 NS_LOG_INFO (this <<" mibSl.slBandwidth "<<(*itMap).second.slBandwidth |
| 4367 <<" mibSl.inCoverage "<<(*itMap).second.inCoverage |
| 4368 <<" mibSl.directFrameNo "<<(*itMap).second.directFrameNo |
| 4369 <<" mibSl.directSubframeNo "<<(*itMap).second.directSubfr
ameNo |
| 4370 <<" mibSl.slssid "<<(*itMap).second.slssid |
| 4371 <<" mibSl.creationTimestamp "<<(*itMap).second.creationTi
mestamp.GetMilliSeconds() |
| 4372 <<" mibSl.rxTimestamp "<<(*itMap).second.rxTimestamp.GetM
illiSeconds()); |
| 4373 |
| 4374 //Instruct the phy to syncronize with maxSrsrpSlssid |
| 4375 m_cphySapProvider->SynchronizeToSyncRef((*itMap).second); |
| 4376 } |
| 4377 } |
| 4378 } |
| 4379 |
| 4380 bool |
| 4381 NistLteUeRrc::IsInTheInnerPartOfTheSyncRefCell(uint16_t slssid, uint16_t offset) |
| 4382 { |
| 4383 NS_LOG_FUNCTION (this << slssid << offset); |
| 4384 |
| 4385 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->GetSlPrec
onfiguration (); |
| 4386 |
| 4387 std::map <std::pair<uint16_t,uint16_t>, SlssMeasValues>::iterator itMap = m_st
oredSlssMeasValues.find(std::pair<uint16_t,uint16_t>(slssid,offset)); |
| 4388 if (itMap == m_storedSlssMeasValues.end ()) |
| 4389 { |
| 4390 NS_LOG_ERROR(" The UE cannot find the S-RSRP measurements for the selected
SyncRef SLSSID " << slssid <<" offset " << offset); |
| 4391 return false; |
| 4392 } |
| 4393 else |
| 4394 { |
| 4395 if ((*itMap).second.srsrp >= preconf.preconfigSync.syncTxThreshOoC) |
| 4396 { |
| 4397 NS_LOG_LOGIC (this << " The SyncRef S-RSRP is above or equal to the co
nfigured syncTxThreshOoC, i.e., the UE is in the inner part of the SyncRef cell"
); |
| 4398 return true; |
| 4399 } |
| 4400 else |
| 4401 { |
| 4402 NS_LOG_LOGIC (this << " The SyncRef S-RSRP is below the configured syn
cTxThreshOoC, i.e., the UE is in the outer part of the SyncRef cell"); |
| 4403 return false; |
| 4404 } |
| 4405 } |
| 4406 } |
| 4407 |
| 4408 void NistLteUeRrc::DoReceiveMibSL (NistLteRrcSap::MasterInformationBlockSL mibSl
) |
| 4409 { |
| 4410 |
| 4411 NS_LOG_FUNCTION (this); |
| 4412 |
| 4413 mibSl.rxTimestamp = Simulator::Now(); |
| 4414 mibSl.rxOffset = Simulator::Now().GetMilliSeconds() % 40; |
| 4415 |
| 4416 NS_LOG_INFO (this <<" UE IMSI "<<m_imsi <<" received MIB-SL "); |
| 4417 NS_LOG_INFO (this <<" mibSl.slBandwidth "<<mibSl.slBandwidth |
| 4418 <<", mibSl.inCoverage "<<mibSl.inCoverage |
| 4419 <<", mibSl.directFrameNo "<<mibSl.directFrameNo |
| 4420 <<", mibSl.directSubframeNo "<<mibSl.directSubframeNo |
| 4421 <<", mibSl.creationTimestamp "<< mibSl.creationTimestamp.GetMilli
Seconds()<<" (ms)" |
| 4422 <<", mibSl.rxTimestamp "<<mibSl.rxTimestamp.GetMilliSeconds()<<"
(ms)" |
| 4423 <<", mibSl.slssid "<<mibSl.slssid |
| 4424 <<", mibSl.rxOffset "<<mibSl.rxOffset); |
| 4425 |
| 4426 |
| 4427 //Store the mib |
| 4428 std::map <std::pair<uint16_t,uint16_t>, NistLteRrcSap::MasterInformationBlockS
L>::iterator itMap |
| 4429 = m_latestMibSlReceived.find (std::pair<uint16_t,uint16_t>(mibSl.slssid, mibSl
.rxOffset)); |
| 4430 |
| 4431 if (itMap == m_latestMibSlReceived.end ()) |
| 4432 { |
| 4433 //Insert new entry |
| 4434 NS_LOG_LOGIC (this << " First received MIB-SL for SyncRef with SLSSID "<<m
ibSl.slssid << " offset " <<mibSl.rxOffset); |
| 4435 m_latestMibSlReceived.insert (std::pair <std::pair<uint16_t,uint16_t>, Nis
tLteRrcSap::MasterInformationBlockSL> (std::pair<uint16_t,uint16_t>(mibSl.slssid
, mibSl.rxOffset), mibSl)); |
| 4436 } |
| 4437 else{ |
| 4438 //Replace the entry |
| 4439 NS_LOG_LOGIC (this << " Updating stored MIB-SL for SyncRef with SLSSID "<<
mibSl.slssid << " offset " <<mibSl.rxOffset); |
| 4440 (*itMap).second.slBandwidth = mibSl.slBandwidth; |
| 4441 (*itMap).second.inCoverage = mibSl.inCoverage; |
| 4442 (*itMap).second.directFrameNo = mibSl.directFrameNo; |
| 4443 (*itMap).second.directSubframeNo = mibSl.directSubframeNo; |
| 4444 (*itMap).second.slssid = mibSl.slssid; |
| 4445 (*itMap).second.rxTimestamp= mibSl.rxTimestamp; |
| 4446 (*itMap).second.creationTimestamp= mibSl.creationTimestamp; |
| 4447 } |
| 4448 //Verify if it is a MIB-SL from the current SyncRef |
| 4449 if(m_hasSyncRef && mibSl.slssid == m_currSyncRef.slssid){ |
| 4450 NS_LOG_LOGIC (this << " The received MIB-SL is from the selected SyncRef (
SLSSID "<<mibSl.slssid << " offset " <<mibSl.rxOffset<<")"); |
| 4451 } |
| 4452 } |
| 4453 |
| 4454 void NistLteUeRrc::DoReportSlssMeasurements ( NistLteUeCphySapUser::NistUeSlssMe
asurementsParameters params, uint64_t slssid, uint16_t offset ) |
| 4455 { |
| 4456 NS_LOG_FUNCTION (this); |
| 4457 |
| 4458 bool useLayer3Filtering = false; |
| 4459 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->GetSlPrec
onfiguration (); |
| 4460 if (preconf.preconfigSync.filterCoefficient != 0){ |
| 4461 NS_LOG_LOGIC (this << " Using L3 filtering"); |
| 4462 useLayer3Filtering = true; |
| 4463 } |
| 4464 |
| 4465 if (m_knownSlssidList.size() > 0 && slssid == 0){ //Measurement for SyncRef se
lection report |
| 4466 |
| 4467 NS_LOG_LOGIC (this << " The report corresponds to the measurement sub-proc
ess"); |
| 4468 |
| 4469 //Storing the measurements of the known SLSSIDs |
| 4470 std::vector <std::pair<uint16_t,uint16_t> >::iterator knownSlssidIit; |
| 4471 for (knownSlssidIit = m_knownSlssidList.begin (); |
| 4472 knownSlssidIit != m_knownSlssidList.end (); ++knownSlssidIit) |
| 4473 { |
| 4474 bool found = false; |
| 4475 std::vector <NistLteUeCphySapUser::NistUeSlssMeasurementReportElement>
::iterator newMeasIt; |
| 4476 for (newMeasIt = params.m_ueSlssMeasurementsList.begin (); |
| 4477 newMeasIt != params.m_ueSlssMeasurementsList.end (); newMeasIt++) |
| 4478 { |
| 4479 if ( (*knownSlssidIit).first == newMeasIt->m_slssid && (*knownSls
sidIit).second == newMeasIt->m_offset) |
| 4480 { |
| 4481 NS_LOG_LOGIC (this <<" UE IMSI "<<m_imsi<< " reported measurem
ents from known SincRef with SLSSID "<<newMeasIt->m_slssid<<" offset "<<newMeasI
t->m_offset<<" S-RSRP "<<newMeasIt->m_srsrp ); |
| 4482 SaveSlssMeasurements(newMeasIt->m_slssid,newMeasIt->m_offset,n
ewMeasIt->m_srsrp,useLayer3Filtering); |
| 4483 m_lastReportedSlssidList.push_back(std::pair<uint16_t,uint16_t
>(newMeasIt->m_slssid,newMeasIt->m_offset)); |
| 4484 found = true; |
| 4485 break; |
| 4486 } |
| 4487 } |
| 4488 if (!found) |
| 4489 { |
| 4490 NS_LOG_LOGIC (this <<" UE IMSI "<<m_imsi<< " did not report measur
ements from known SincRef with SLSSID"<<(*knownSlssidIit).first << " offset "<<(
*knownSlssidIit).second); |
| 4491 } |
| 4492 } |
| 4493 //Adding the measures of the not known SLSSIDs |
| 4494 std::vector <NistLteUeCphySapUser::NistUeSlssMeasurementReportElement>::it
erator newMeasIt; |
| 4495 for (newMeasIt = params.m_ueSlssMeasurementsList.begin (); |
| 4496 newMeasIt != params.m_ueSlssMeasurementsList.end (); newMeasIt++) |
| 4497 { |
| 4498 bool found = false; |
| 4499 std::vector <std::pair<uint16_t,uint16_t> >::iterator knownSlssidIit; |
| 4500 for (knownSlssidIit = m_knownSlssidList.begin (); |
| 4501 knownSlssidIit != m_knownSlssidList.end (); ++knownSlssidIit) |
| 4502 { |
| 4503 if ( (*knownSlssidIit).first == newMeasIt->m_slssid && (*knownSls
sidIit).second == newMeasIt->m_offset) |
| 4504 { |
| 4505 found = true; |
| 4506 break; |
| 4507 } |
| 4508 } |
| 4509 if(!found) |
| 4510 { |
| 4511 NS_LOG_LOGIC (this <<" UE IMSI "<<m_imsi<< " reported measurements
from not known SincRef with SLSSID "<<newMeasIt->m_slssid<< " offset "<<newMeas
It->m_offset<<" S-RSRP "<<newMeasIt->m_srsrp); |
| 4512 SaveSlssMeasurements(newMeasIt->m_slssid,newMeasIt->m_offset, newM
easIt->m_srsrp,useLayer3Filtering); |
| 4513 m_lastReportedSlssidList.push_back(std::pair<uint16_t,uint16_t>(ne
wMeasIt->m_slssid,newMeasIt->m_offset)); |
| 4514 found = true; |
| 4515 } |
| 4516 } |
| 4517 } |
| 4518 else if (m_knownSlssidList.size() == 0) //The first report with detected SyncR
efs |
| 4519 { |
| 4520 NS_LOG_LOGIC (this << " The report corresponds to the first measurement su
b-process with detected SyncRefs"); |
| 4521 |
| 4522 std::vector <NistLteUeCphySapUser::NistUeSlssMeasurementReportElement>::it
erator newMeasIt; |
| 4523 for (newMeasIt = params.m_ueSlssMeasurementsList.begin (); |
| 4524 newMeasIt != params.m_ueSlssMeasurementsList.end (); ++newMeasIt) |
| 4525 { |
| 4526 NS_LOG_LOGIC (this <<" UE IMSI "<<m_imsi<< " reported measurements fro
m not known SincRef with SLSSID "<<newMeasIt->m_slssid<< " offset "<<newMeasIt->
m_offset<<" S-RSRP "<<newMeasIt->m_srsrp); |
| 4527 SaveSlssMeasurements(newMeasIt->m_slssid,newMeasIt->m_offset, newMeasI
t->m_srsrp,useLayer3Filtering); |
| 4528 m_lastReportedSlssidList.push_back(std::pair<uint16_t,uint16_t>(newMea
sIt->m_slssid,newMeasIt->m_offset)); |
| 4529 |
| 4530 } |
| 4531 } |
| 4532 else if (slssid > 0)//Specific SLSSID report (i.e., evaluation of selected Syn
cRef) |
| 4533 { |
| 4534 NS_LOG_LOGIC (this << " The report corresponds to the evaluation sub-proce
ss"); |
| 4535 |
| 4536 std::vector <NistLteUeCphySapUser::NistUeSlssMeasurementReportElement>::it
erator newMeasIt; |
| 4537 if (params.m_ueSlssMeasurementsList.size() == 1) |
| 4538 { |
| 4539 newMeasIt = params.m_ueSlssMeasurementsList.begin(); |
| 4540 if(newMeasIt->m_slssid == slssid) |
| 4541 { |
| 4542 NS_LOG_LOGIC (this <<" UE IMSI "<<m_imsi<< " reported measurements
from selected SincRef with SLSSID "<<newMeasIt->m_slssid<< " offset "<<newMeasI
t->m_offset<<" S-RSRP "<<newMeasIt->m_srsrp); |
| 4543 SaveSlssMeasurements(newMeasIt->m_slssid,newMeasIt->m_offset, newM
easIt->m_srsrp,useLayer3Filtering); |
| 4544 m_lastReportedSlssidList.push_back(std::pair<uint16_t,uint16_t>(sl
ssid,offset)); |
| 4545 } |
| 4546 else |
| 4547 { |
| 4548 NS_LOG_ERROR(" The S-RSRP measurements does not correspond to the
intended SyncRef with SLSSID "<<slssid<<" offset "<<offset); |
| 4549 } |
| 4550 } |
| 4551 else if (params.m_ueSlssMeasurementsList.size() == 0) //The SyncRef disapp
eared |
| 4552 { |
| 4553 NS_LOG_LOGIC (this <<" The UE is unable to find the S-RSRP measurement
s of the selected SyncRef with SLSSID "<<slssid<<" offset "<<offset); |
| 4554 } |
| 4555 else if (params.m_ueSlssMeasurementsList.size() > 1) |
| 4556 { |
| 4557 NS_LOG_ERROR(" The S-RSRP measurement report intended for evaluation o
f selected SyncRef has more than one SyncRef reported "); |
| 4558 } |
| 4559 } |
| 4560 |
| 4561 //Selection of the SyncRef |
| 4562 if(m_hasSyncRef && slssid == 0) |
| 4563 { |
| 4564 NS_LOG_LOGIC (this <<" Evaluating validity of current SyncRef"); |
| 4565 |
| 4566 NistLteRrcSap::SlPreconfiguration preconf = m_sidelinkConfiguration->GetSl
Preconfiguration (); |
| 4567 //Select strongest candidate |
| 4568 uint16_t maxSrsrpSlssid = 0; |
| 4569 uint64_t maxSrsrpOffset = 0; |
| 4570 bool syncRefDetected = false; |
| 4571 double maxSrsrp = -std::numeric_limits<double>::infinity (); |
| 4572 std::vector <std::pair<uint16_t,uint16_t> >::iterator RepIt; |
| 4573 for (RepIt = m_lastReportedSlssidList.begin (); RepIt != m_lastReportedSls
sidList.end (); ++RepIt) |
| 4574 { |
| 4575 if ( (*RepIt).first == m_currSyncRef.slssid && (*RepIt).second == m_cu
rrSyncRef.rxOffset){ |
| 4576 syncRefDetected = true; |
| 4577 } |
| 4578 std::map <std::pair<uint16_t,uint16_t>, SlssMeasValues>::iterator it =
m_storedSlssMeasValues.find(std::pair<uint16_t,uint16_t>(*RepIt)); |
| 4579 if (it == m_storedSlssMeasValues.end ()) |
| 4580 { |
| 4581 NS_LOG_ERROR(" The UE cannot find the S-RSRP measurements for the
detected SyncRef SLSSID " << RepIt->first <<" offset " <<RepIt->second ); |
| 4582 } |
| 4583 else |
| 4584 { |
| 4585 if (maxSrsrp < it->second.srsrp) |
| 4586 { |
| 4587 maxSrsrpSlssid = it->first.first; |
| 4588 maxSrsrpOffset = it->first.second; |
| 4589 maxSrsrp = it->second.srsrp; |
| 4590 } |
| 4591 } |
| 4592 } |
| 4593 |
| 4594 NS_LOG_INFO (this <<" The strongest SyncRef SLSSID "<< maxSrsrpSlssid << "
offset "<<maxSrsrpOffset <<" has a S-RSRP of "<<maxSrsrp<<" dBm" ); |
| 4595 //Strongest candidate exceeds the minimum required? |
| 4596 if (maxSrsrpSlssid != 0 && maxSrsrp - m_minSrsrp > preconf.preconfigSync.
syncRefMinHyst) |
| 4597 { |
| 4598 //Yes |
| 4599 NS_LOG_LOGIC(this <<" The strongest candidate S-RSRP exceeds the minim
um required by the corresponding threshold syncRefMinHyst" ); |
| 4600 |
| 4601 //The selected SyncRef was detected? |
| 4602 if (!syncRefDetected) |
| 4603 { |
| 4604 //No... consider the selected SyncRef not valid |
| 4605 NS_LOG_LOGIC(this <<" The selected SyncRef was not detected... Con
sidering it not valid" ); |
| 4606 m_hasSyncRef = false; |
| 4607 } |
| 4608 else |
| 4609 { |
| 4610 //Yes |
| 4611 std::map <std::pair<uint16_t,uint16_t>, SlssMeasValues>::iterator
itMap = m_storedSlssMeasValues.find (std::pair<uint16_t,uint16_t>(m_currSyncRef.
slssid,m_currSyncRef.rxOffset)); |
| 4612 if (itMap == m_storedSlssMeasValues.end ()) |
| 4613 { |
| 4614 NS_LOG_LOGIC(this <<" The UE cannot find the S-RSRP measuremen
ts for the selected SyncRef... Considering it not valid" ); |
| 4615 m_hasSyncRef = false; |
| 4616 } |
| 4617 else |
| 4618 { |
| 4619 //Strongest candidate better than the selected SyncRef? |
| 4620 if (maxSrsrp - (*itMap).second.srsrp > preconf.preconfigSync.s
yncRefDiffHyst) |
| 4621 { |
| 4622 //Yes... Consider not valid the selected SyncRef |
| 4623 NS_LOG_LOGIC(this <<" The strongest candidate S-RSRP excee
ds the selected SyncRef one by the corresponding threshold syncRefDiffHyst... Co
nsidering the selected SyncRef not valid" ); |
| 4624 m_hasSyncRef = false; |
| 4625 } |
| 4626 else |
| 4627 { |
| 4628 //No... Keep the selected SyncRef |
| 4629 NS_LOG_LOGIC(this <<" The strongest candidate S-RSRP does
not exceed the selected SyncRef one by the corresponding threshold syncRefDiffHy
st... Keeping the selected SyncRef" ); |
| 4630 } |
| 4631 } |
| 4632 } |
| 4633 } |
| 4634 else |
| 4635 { |
| 4636 //No... Keep the selected SyncRef |
| 4637 NS_LOG_LOGIC(this <<" The strongest candidate S-RSRP does not exceed t
he minimum required by the corresponding threshold syncRefMinHyst" ); |
| 4638 } |
| 4639 } |
| 4640 if(!m_hasSyncRef && slssid == 0) |
| 4641 { |
| 4642 NS_LOG_LOGIC(this <<" The UE does not have a (valid) selected SyncRef... S
electing the strongest candidate if approppriate" ); |
| 4643 //Evaluate candidates for selection of SyncRef |
| 4644 SynchronizeToStrongestSyncRef (); |
| 4645 } |
| 4646 |
| 4647 if (m_hasSyncRef && slssid > 0) |
| 4648 { |
| 4649 NS_LOG_LOGIC(this <<" Evaluating S-RSRP measurements of the selected SyncR
ef" ); |
| 4650 |
| 4651 if(IsInTheInnerPartOfTheSyncRefCell(m_currSyncRef.slssid, m_currSyncRef.rx
Offset)) |
| 4652 { |
| 4653 NS_LOG_LOGIC (this << " the UE is in the inner cell of the selected Sy
ncRef"); |
| 4654 if(m_slssTransmissionActive == true ) |
| 4655 { |
| 4656 NS_LOG_LOGIC (this << " the UE was transmitting SLSS... Deactivati
ng the SLSS transmission"); |
| 4657 DeactivateSlssTransmission (); |
| 4658 } |
| 4659 m_inInnerCellOfSyncRef = true; |
| 4660 } |
| 4661 else |
| 4662 { |
| 4663 NS_LOG_LOGIC (this << " the UE is in the outer cell of the selected Sy
ncRef"); |
| 4664 |
| 4665 if(m_inInnerCellOfSyncRef && m_hasDataToTransmit) |
| 4666 { |
| 4667 // It was in the inner cell, but not anymore |
| 4668 |
| 4669 NS_LOG_LOGIC (this << " the UE was in the outer cell of the select
ed SyncRef (but not anymore) " |
| 4670 "and it is transmitting sidelink communication... Activating S
LSS transmission"); |
| 4671 ActivateSlssTransmission (); |
| 4672 } |
| 4673 m_inInnerCellOfSyncRef = false; |
| 4674 } |
| 4675 } |
| 4676 m_lastReportedSlssidList.clear(); |
| 4677 } |
| 4678 |
| 4679 void |
| 4680 NistLteUeRrc::DoReportChangeOfSyncRef (NistLteRrcSap::MasterInformationBlockSL m
ibSl, uint16_t frameNo, uint16_t subFrameNo) |
| 4681 { |
| 4682 NS_LOG_FUNCTION (this); |
| 4683 |
| 4684 m_hasSyncRef = true; |
| 4685 |
| 4686 uint16_t previousFrameNo = m_currFrameNo; |
| 4687 uint16_t previousSubFrameNo = m_currSubframeNo; |
| 4688 |
| 4689 //Save the current subframe indication |
| 4690 SaveSubframeIndication(frameNo, subFrameNo); |
| 4691 |
| 4692 SlChangeOfSyncRefStatParameters param; |
| 4693 param.imsi=m_imsi; |
| 4694 param.prevSlssid =m_slssId; |
| 4695 param.prevRxOffset=m_currSyncRef.rxOffset; |
| 4696 param.prevFrameNo=previousFrameNo; |
| 4697 param.prevSubframeNo=previousSubFrameNo; |
| 4698 |
| 4699 //Storing the value of the MIB (Note this is not the current frameNo and subfr
ameNo) |
| 4700 m_currSyncRef.directFrameNo = mibSl.directFrameNo; |
| 4701 m_currSyncRef.directSubframeNo = mibSl.directSubframeNo; |
| 4702 m_currSyncRef.inCoverage = mibSl.inCoverage; |
| 4703 m_currSyncRef.rxTimestamp = mibSl.rxTimestamp; |
| 4704 m_currSyncRef.creationTimestamp = mibSl.creationTimestamp; |
| 4705 m_currSyncRef.slBandwidth = mibSl.slBandwidth; |
| 4706 m_currSyncRef.slssid = mibSl.slssid; |
| 4707 m_currSyncRef.rxOffset = mibSl.rxOffset; |
| 4708 |
| 4709 m_slssId = mibSl.slssid; |
| 4710 |
| 4711 param.currSlssid=m_slssId; |
| 4712 param.currRxOffset=mibSl.rxOffset; |
| 4713 param.currFrameNo=m_currFrameNo; |
| 4714 param.currSubframeNo=m_currSubframeNo; |
| 4715 |
| 4716 m_ChangeOfSyncRefTrace(param); |
| 4717 |
| 4718 NS_LOG_INFO (this <<" UE IMSI "<<m_imsi <<" reported successful change of Sync
Ref, selected SyncRef SLSSID "<< mibSl.slssid <<"offset "<< mibSl.rxOffset); |
| 4719 } |
| 4720 |
| 4721 void NistLteUeRrc::DoReportSubframeIndication(uint16_t frameNo, uint16_t subFram
eNo) |
| 4722 { |
| 4723 //NS_LOG_FUNCTION (this << frameNo << subFrameNo ); // Too much overhead as it
is called every ms |
| 4724 SaveSubframeIndication(frameNo, subFrameNo); |
| 4725 } |
| 4726 |
| 4727 void |
| 4728 NistLteUeRrc::DoNotifyMacHasSlDataToSend() |
| 4729 { |
| 4730 NS_LOG_FUNCTION (this); |
| 4731 if (m_slssTransmissionEnabled){ |
| 4732 NS_LOG_LOGIC(this <<" The MAC notified that it has data to send, and SLSS
transmissions are enabled... Initiating SLSS transmissions" ); |
| 4733 InitiateSlssTransmission(); |
| 4734 } |
| 4735 } |
| 4736 |
| 4737 void |
| 4738 NistLteUeRrc::DoNotifyMacHasNotSlDataToSend() |
| 4739 { |
| 4740 NS_LOG_FUNCTION (this); |
| 4741 if (m_slssTransmissionEnabled){ |
| 4742 NS_LOG_LOGIC(this <<" The MAC notified that it does not have anymore data
to send, and SLSS transmissions are enabled... Stoping SLSS transmissions" ); |
| 4743 StopSlssTransmission(); |
| 4744 } |
| 4745 } |
| 4746 |
| 4747 } // namespace ns3 |
| 4748 |
OLD | NEW |