OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2018 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: Manuel Requena <manuel.requena@cttc.es> |
| 19 * (based on epc-sgw-pgw-application.cc) |
| 20 */ |
| 21 |
| 22 #include "ns3/log.h" |
| 23 #include "ns3/abort.h" |
| 24 #include "ns3/mac48-address.h" |
| 25 #include "ns3/ipv4.h" |
| 26 #include "ns3/ipv4-l3-protocol.h" |
| 27 #include "ns3/ipv6.h" |
| 28 #include "ns3/ipv6-header.h" |
| 29 #include "ns3/ipv6-l3-protocol.h" |
| 30 #include "ns3/inet-socket-address.h" |
| 31 #include "ns3/epc-gtpu-header.h" |
| 32 #include "ns3/epc-pgw-application.h" |
| 33 |
| 34 namespace ns3 { |
| 35 |
| 36 NS_LOG_COMPONENT_DEFINE ("EpcPgwApplication"); |
| 37 |
| 38 |
| 39 ///////////////////////// |
| 40 // UeInfo |
| 41 ///////////////////////// |
| 42 |
| 43 EpcPgwApplication::UeInfo::UeInfo () |
| 44 { |
| 45 NS_LOG_FUNCTION (this); |
| 46 } |
| 47 |
| 48 void |
| 49 EpcPgwApplication::UeInfo::AddBearer (uint8_t bearerId, uint32_t teid, Ptr<EpcTf
t> tft) |
| 50 { |
| 51 NS_LOG_FUNCTION (this << (uint16_t) bearerId << teid << tft); |
| 52 m_teidByBearerIdMap[bearerId] = teid; |
| 53 return m_tftClassifier.Add (tft, teid); |
| 54 } |
| 55 |
| 56 void |
| 57 EpcPgwApplication::UeInfo::RemoveBearer (uint8_t bearerId) |
| 58 { |
| 59 NS_LOG_FUNCTION (this << (uint16_t) bearerId); |
| 60 m_teidByBearerIdMap.erase (bearerId); |
| 61 } |
| 62 |
| 63 uint32_t |
| 64 EpcPgwApplication::UeInfo::Classify (Ptr<Packet> p, uint16_t protocolNumber) |
| 65 { |
| 66 NS_LOG_FUNCTION (this << p); |
| 67 // we hardcode DOWNLINK direction since the PGW is expected to |
| 68 // classify only downlink packets (uplink packets will go to the |
| 69 // internet without any classification). |
| 70 return m_tftClassifier.Classify (p, EpcTft::DOWNLINK, protocolNumber); |
| 71 } |
| 72 |
| 73 Ipv4Address |
| 74 EpcPgwApplication::UeInfo::GetSgwAddr () |
| 75 { |
| 76 return m_sgwAddr; |
| 77 } |
| 78 |
| 79 void |
| 80 EpcPgwApplication::UeInfo::SetSgwAddr (Ipv4Address sgwAddr) |
| 81 { |
| 82 m_sgwAddr = sgwAddr; |
| 83 } |
| 84 |
| 85 Ipv4Address· |
| 86 EpcPgwApplication::UeInfo::GetUeAddr () |
| 87 { |
| 88 return m_ueAddr; |
| 89 } |
| 90 |
| 91 void |
| 92 EpcPgwApplication::UeInfo::SetUeAddr (Ipv4Address ueAddr) |
| 93 { |
| 94 m_ueAddr = ueAddr; |
| 95 } |
| 96 |
| 97 Ipv6Address· |
| 98 EpcPgwApplication::UeInfo::GetUeAddr6 () |
| 99 { |
| 100 return m_ueAddr6; |
| 101 } |
| 102 |
| 103 void |
| 104 EpcPgwApplication::UeInfo::SetUeAddr6 (Ipv6Address ueAddr) |
| 105 { |
| 106 m_ueAddr6 = ueAddr; |
| 107 } |
| 108 |
| 109 ///////////////////////// |
| 110 // EpcPgwApplication |
| 111 ///////////////////////// |
| 112 |
| 113 TypeId |
| 114 EpcPgwApplication::GetTypeId (void) |
| 115 { |
| 116 static TypeId tid = TypeId ("ns3::EpcPgwApplication") |
| 117 .SetParent<Object> () |
| 118 .SetGroupName ("Lte") |
| 119 .AddTraceSource ("RxFromTun", |
| 120 "Receive data packets from internet in Tunnel NetDevice", |
| 121 MakeTraceSourceAccessor (&EpcPgwApplication::m_rxTunPktTrac
e), |
| 122 "ns3::EpcPgwApplication::RxTracedCallback") |
| 123 .AddTraceSource ("RxFromS1u", |
| 124 "Receive data packets from S5 Socket", |
| 125 MakeTraceSourceAccessor (&EpcPgwApplication::m_rxS5PktTrace
), |
| 126 "ns3::EpcPgwApplication::RxTracedCallback") |
| 127 ; |
| 128 return tid; |
| 129 } |
| 130 |
| 131 void |
| 132 EpcPgwApplication::DoDispose () |
| 133 { |
| 134 NS_LOG_FUNCTION (this); |
| 135 m_s5uSocket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ()); |
| 136 m_s5uSocket = 0; |
| 137 m_s5cSocket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ()); |
| 138 m_s5cSocket = 0; |
| 139 } |
| 140 |
| 141 EpcPgwApplication::EpcPgwApplication (const Ptr<VirtualNetDevice> tunDevice, Ipv
4Address s5Addr, |
| 142 const Ptr<Socket> s5uSocket, const Ptr<Soc
ket> s5cSocket) |
| 143 : m_pgwS5Addr (s5Addr), |
| 144 m_s5uSocket (s5uSocket), |
| 145 m_s5cSocket (s5cSocket), |
| 146 m_tunDevice (tunDevice), |
| 147 m_gtpuUdpPort (2152), // fixed by the standard |
| 148 m_gtpcUdpPort (2123) // fixed by the standard |
| 149 { |
| 150 NS_LOG_FUNCTION (this << tunDevice << s5Addr << s5uSocket << s5cSocket); |
| 151 m_s5uSocket->SetRecvCallback (MakeCallback (&EpcPgwApplication::RecvFromS5uSoc
ket, this)); |
| 152 m_s5cSocket->SetRecvCallback (MakeCallback (&EpcPgwApplication::RecvFromS5cSoc
ket, this)); |
| 153 } |
| 154 |
| 155 EpcPgwApplication::~EpcPgwApplication () |
| 156 { |
| 157 NS_LOG_FUNCTION (this); |
| 158 } |
| 159 |
| 160 bool |
| 161 EpcPgwApplication::RecvFromTunDevice (Ptr<Packet> packet, const Address& source,
const Address& dest, uint16_t protocolNumber) |
| 162 { |
| 163 NS_LOG_FUNCTION (this << source << dest << protocolNumber << packet << packet-
>GetSize ()); |
| 164 m_rxTunPktTrace (packet->Copy ()); |
| 165 |
| 166 // get IP address of UE |
| 167 if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER) |
| 168 { |
| 169 Ipv4Header ipv4Header; |
| 170 packet->PeekHeader (ipv4Header); |
| 171 Ipv4Address ueAddr = ipv4Header.GetDestination (); |
| 172 NS_LOG_LOGIC ("packet addressed to UE " << ueAddr); |
| 173 |
| 174 // find corresponding UeInfo address |
| 175 std::map<Ipv4Address, Ptr<UeInfo> >::iterator it = m_ueInfoByAddrMap.find
(ueAddr); |
| 176 if (it == m_ueInfoByAddrMap.end ()) |
| 177 { |
| 178 NS_LOG_WARN ("unknown UE address " << ueAddr); |
| 179 } |
| 180 else |
| 181 { |
| 182 Ipv4Address sgwAddr = it->second->GetSgwAddr (); |
| 183 uint32_t teid = it->second->Classify (packet, protocolNumber); |
| 184 if (teid == 0) |
| 185 { |
| 186 NS_LOG_WARN ("no matching bearer for this packet"); |
| 187 } |
| 188 else |
| 189 { |
| 190 SendToS5uSocket (packet, sgwAddr, teid); |
| 191 } |
| 192 } |
| 193 } |
| 194 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER) |
| 195 { |
| 196 Ipv6Header ipv6Header; |
| 197 packet->PeekHeader (ipv6Header); |
| 198 Ipv6Address ueAddr = ipv6Header.GetDestinationAddress (); |
| 199 NS_LOG_LOGIC ("packet addressed to UE " << ueAddr); |
| 200 |
| 201 // find corresponding UeInfo address |
| 202 std::map<Ipv6Address, Ptr<UeInfo> >::iterator it = m_ueInfoByAddrMap6.find
(ueAddr); |
| 203 if (it == m_ueInfoByAddrMap6.end ()) |
| 204 { |
| 205 NS_LOG_WARN ("unknown UE address " << ueAddr); |
| 206 } |
| 207 else |
| 208 { |
| 209 Ipv4Address sgwAddr = it->second->GetSgwAddr (); |
| 210 uint32_t teid = it->second->Classify (packet, protocolNumber); |
| 211 if (teid == 0) |
| 212 { |
| 213 NS_LOG_WARN ("no matching bearer for this packet"); |
| 214 } |
| 215 else |
| 216 { |
| 217 SendToS5uSocket (packet, sgwAddr, teid); |
| 218 } |
| 219 } |
| 220 } |
| 221 else |
| 222 { |
| 223 NS_ABORT_MSG ("Unknown IP type"); |
| 224 } |
| 225 |
| 226 // there is no reason why we should notify the TUN |
| 227 // VirtualNetDevice that he failed to send the packet: if we receive |
| 228 // any bogus packet, it will just be silently discarded. |
| 229 const bool succeeded = true; |
| 230 return succeeded; |
| 231 } |
| 232 |
| 233 void |
| 234 EpcPgwApplication::RecvFromS5uSocket (Ptr<Socket> socket) |
| 235 { |
| 236 NS_LOG_FUNCTION (this << socket); |
| 237 NS_ASSERT (socket == m_s5uSocket); |
| 238 Ptr<Packet> packet = socket->Recv (); |
| 239 m_rxS5PktTrace (packet->Copy ()); |
| 240 |
| 241 GtpuHeader gtpu; |
| 242 packet->RemoveHeader (gtpu); |
| 243 uint32_t teid = gtpu.GetTeid (); |
| 244 |
| 245 SendToTunDevice (packet, teid); |
| 246 } |
| 247 |
| 248 void |
| 249 EpcPgwApplication::RecvFromS5cSocket (Ptr<Socket> socket) |
| 250 { |
| 251 NS_LOG_FUNCTION (this << socket); |
| 252 NS_ASSERT (socket == m_s5cSocket); |
| 253 Ptr<Packet> packet = socket->Recv (); |
| 254 GtpcHeader header; |
| 255 packet->PeekHeader (header); |
| 256 uint16_t msgType = header.GetMessageType (); |
| 257 |
| 258 switch (msgType) |
| 259 { |
| 260 case GtpcHeader::CreateSessionRequest: |
| 261 DoRecvCreateSessionRequest (packet); |
| 262 break; |
| 263 |
| 264 case GtpcHeader::ModifyBearerRequest: |
| 265 DoRecvModifyBearerRequest (packet); |
| 266 break; |
| 267 |
| 268 case GtpcHeader::DeleteBearerCommand: |
| 269 DoRecvDeleteBearerCommand (packet); |
| 270 break; |
| 271 |
| 272 case GtpcHeader::DeleteBearerResponse: |
| 273 DoRecvDeleteBearerResponse (packet); |
| 274 break; |
| 275 |
| 276 default: |
| 277 NS_FATAL_ERROR ("GTP-C message not supported"); |
| 278 break; |
| 279 } |
| 280 } |
| 281 |
| 282 void |
| 283 EpcPgwApplication::DoRecvCreateSessionRequest (Ptr<Packet> packet) |
| 284 { |
| 285 NS_LOG_FUNCTION (this); |
| 286 |
| 287 GtpcCreateSessionRequestMessage msg; |
| 288 packet->RemoveHeader (msg); |
| 289 uint64_t imsi = msg.GetImsi (); |
| 290 uint16_t cellId = msg.GetUliEcgi (); |
| 291 NS_LOG_DEBUG ("cellId " << cellId << " imsi " << (uint16_t)imsi); |
| 292 |
| 293 std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi
); |
| 294 NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); |
| 295 ueit->second->SetSgwAddr (m_sgwS5Addr); |
| 296 |
| 297 GtpcHeader::Fteid_t sgwS5cFteid = msg.GetSenderCpFteid (); |
| 298 NS_ASSERT_MSG (sgwS5cFteid.interfaceType == GtpcHeader::S5_SGW_GTPC, |
| 299 "Wrong interface type"); |
| 300 |
| 301 GtpcCreateSessionResponseMessage msgOut; |
| 302 msgOut.SetTeid (sgwS5cFteid.teid); |
| 303 msgOut.SetCause (GtpcCreateSessionResponseMessage::REQUEST_ACCEPTED); |
| 304 |
| 305 GtpcHeader::Fteid_t pgwS5cFteid; |
| 306 pgwS5cFteid.interfaceType = GtpcHeader::S5_PGW_GTPC; |
| 307 pgwS5cFteid.teid = sgwS5cFteid.teid; |
| 308 pgwS5cFteid.addr = m_pgwS5Addr; |
| 309 msgOut.SetSenderCpFteid (pgwS5cFteid); |
| 310 |
| 311 std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerCon
texts = |
| 312 msg.GetBearerContextsToBeCreated (); |
| 313 NS_LOG_DEBUG ("BearerContextsToBeCreated size = " << bearerContexts.size ()); |
| 314 |
| 315 std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContex
tsCreated; |
| 316 for (auto &bearerContext : bearerContexts) |
| 317 { |
| 318 uint32_t teid = bearerContext.sgwS5uFteid.teid; |
| 319 NS_LOG_DEBUG ("bearerId " << (uint16_t)bearerContext.epsBearerId << |
| 320 " SGW " << bearerContext.sgwS5uFteid.addr << " TEID " << tei
d); |
| 321 |
| 322 ueit->second->AddBearer (bearerContext.epsBearerId, teid, bearerContext.tf
t); |
| 323 |
| 324 GtpcCreateSessionResponseMessage::BearerContextCreated bearerContextOut; |
| 325 bearerContextOut.fteid.interfaceType = GtpcHeader::S5_PGW_GTPU; |
| 326 bearerContextOut.fteid.teid = teid; |
| 327 bearerContextOut.fteid.addr = m_pgwS5Addr; |
| 328 bearerContextOut.epsBearerId = bearerContext.epsBearerId; |
| 329 bearerContextOut.bearerLevelQos = bearerContext.bearerLevelQos; |
| 330 bearerContextOut.tft = bearerContext.tft; |
| 331 bearerContextsCreated.push_back (bearerContextOut); |
| 332 } |
| 333 |
| 334 NS_LOG_DEBUG ("BearerContextsCreated size = " << bearerContextsCreated.size ()
); |
| 335 msgOut.SetBearerContextsCreated (bearerContextsCreated); |
| 336 msgOut.SetTeid (sgwS5cFteid.teid); |
| 337 msgOut.ComputeMessageLength (); |
| 338 |
| 339 Ptr<Packet> packetOut = Create <Packet> (); |
| 340 packetOut->AddHeader (msgOut); |
| 341 NS_LOG_DEBUG ("Send CreateSessionResponse to SGW " << sgwS5cFteid.addr); |
| 342 m_s5cSocket->SendTo (packetOut, 0, InetSocketAddress (sgwS5cFteid.addr, m_gtpc
UdpPort)); |
| 343 } |
| 344 |
| 345 void |
| 346 EpcPgwApplication::DoRecvModifyBearerRequest (Ptr<Packet> packet) |
| 347 { |
| 348 NS_LOG_FUNCTION (this); |
| 349 |
| 350 GtpcModifyBearerRequestMessage msg; |
| 351 packet->RemoveHeader (msg); |
| 352 uint8_t imsi = msg.GetImsi (); |
| 353 uint16_t cellId = msg.GetUliEcgi (); |
| 354 NS_LOG_DEBUG ("cellId " << cellId << "IMSI " << (uint16_t)imsi); |
| 355 |
| 356 std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi
); |
| 357 NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);· |
| 358 ueit->second->SetSgwAddr (m_sgwS5Addr); |
| 359 |
| 360 std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerCon
texts = |
| 361 msg.GetBearerContextsToBeModified (); |
| 362 NS_LOG_DEBUG ("BearerContextsToBeModified size = " << bearerContexts.size ()); |
| 363 |
| 364 for (auto &bearerContext : bearerContexts) |
| 365 { |
| 366 Ipv4Address sgwAddr = bearerContext.fteid.addr; |
| 367 uint32_t teid = bearerContext.fteid.teid; |
| 368 NS_LOG_DEBUG ("bearerId " << (uint16_t)bearerContext.epsBearerId << |
| 369 " SGW " << sgwAddr << " TEID " << teid); |
| 370 } |
| 371 |
| 372 GtpcModifyBearerResponseMessage msgOut; |
| 373 msgOut.SetCause (GtpcIes::REQUEST_ACCEPTED); |
| 374 msgOut.SetTeid (imsi); |
| 375 msgOut.ComputeMessageLength (); |
| 376 |
| 377 Ptr<Packet> packetOut = Create <Packet> (); |
| 378 packetOut->AddHeader (msgOut); |
| 379 NS_LOG_DEBUG ("Send ModifyBearerResponse to SGW " << m_sgwS5Addr); |
| 380 m_s5cSocket->SendTo (packetOut, 0, InetSocketAddress (m_sgwS5Addr, m_gtpcUdpPo
rt)); |
| 381 } |
| 382 |
| 383 void |
| 384 EpcPgwApplication::DoRecvDeleteBearerCommand (Ptr<Packet> packet) |
| 385 { |
| 386 NS_LOG_FUNCTION (this); |
| 387 |
| 388 GtpcDeleteBearerCommandMessage msg; |
| 389 packet->RemoveHeader (msg); |
| 390 |
| 391 std::list<uint8_t> epsBearerIds; |
| 392 for (auto &bearerContext : msg.GetBearerContexts ()) |
| 393 { |
| 394 NS_LOG_DEBUG ("ebid " << bearerContext.m_epsBearerId); |
| 395 epsBearerIds.push_back (bearerContext.m_epsBearerId); |
| 396 } |
| 397 |
| 398 GtpcDeleteBearerRequestMessage msgOut; |
| 399 msgOut.SetEpsBearerIds (epsBearerIds); |
| 400 msgOut.SetTeid (msg.GetTeid ()); |
| 401 msgOut.ComputeMessageLength (); |
| 402 |
| 403 Ptr<Packet> packetOut = Create <Packet> (); |
| 404 packetOut->AddHeader (msgOut); |
| 405 NS_LOG_DEBUG ("Send DeleteBearerRequest to SGW " << m_sgwS5Addr); |
| 406 m_s5cSocket->SendTo (packetOut, 0, InetSocketAddress (m_sgwS5Addr, m_gtpcUdpPo
rt)); |
| 407 } |
| 408 |
| 409 void |
| 410 EpcPgwApplication::DoRecvDeleteBearerResponse (Ptr<Packet> packet) |
| 411 { |
| 412 NS_LOG_FUNCTION (this); |
| 413 |
| 414 GtpcDeleteBearerResponseMessage msg; |
| 415 packet->RemoveHeader (msg); |
| 416 |
| 417 uint64_t imsi = msg.GetTeid (); |
| 418 std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi
); |
| 419 NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); |
| 420 |
| 421 for (auto &epsBearerId : msg.GetEpsBearerIds ()) |
| 422 { |
| 423 // Remove de-activated bearer contexts from PGW side |
| 424 ueit->second->RemoveBearer (epsBearerId); |
| 425 } |
| 426 } |
| 427 |
| 428 |
| 429 void |
| 430 EpcPgwApplication::SendToTunDevice (Ptr<Packet> packet, uint32_t teid) |
| 431 { |
| 432 NS_LOG_FUNCTION (this << packet << teid); |
| 433 NS_LOG_LOGIC ("packet size: " << packet->GetSize () << " bytes"); |
| 434 |
| 435 uint8_t ipType; |
| 436 packet->CopyData (&ipType, 1); |
| 437 ipType = (ipType>>4) & 0x0f; |
| 438 |
| 439 uint16_t protocol = 0; |
| 440 if (ipType == 0x04) |
| 441 { |
| 442 protocol = 0x0800; |
| 443 } |
| 444 else if (ipType == 0x06) |
| 445 { |
| 446 protocol = 0x86DD; |
| 447 } |
| 448 else |
| 449 { |
| 450 NS_ABORT_MSG ("Unknown IP type"); |
| 451 } |
| 452 |
| 453 m_tunDevice->Receive (packet, protocol, m_tunDevice->GetAddress (), m_tunDevic
e->GetAddress (), NetDevice::PACKET_HOST); |
| 454 } |
| 455 |
| 456 void |
| 457 EpcPgwApplication::SendToS5uSocket (Ptr<Packet> packet, Ipv4Address sgwAddr, uin
t32_t teid) |
| 458 { |
| 459 NS_LOG_FUNCTION (this << packet << sgwAddr << teid); |
| 460 |
| 461 GtpuHeader gtpu; |
| 462 gtpu.SetTeid (teid); |
| 463 // From 3GPP TS 29.281 v10.0.0 Section 5.1 |
| 464 // Length of the payload + the non obligatory GTP-U header |
| 465 gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8); |
| 466 packet->AddHeader (gtpu); |
| 467 uint32_t flags = 0; |
| 468 m_s5uSocket->SendTo (packet, flags, InetSocketAddress (sgwAddr, m_gtpuUdpPort)
); |
| 469 } |
| 470 |
| 471 |
| 472 void |
| 473 EpcPgwApplication::AddSgw (Ipv4Address sgwS5Addr) |
| 474 { |
| 475 NS_LOG_FUNCTION (this << sgwS5Addr); |
| 476 m_sgwS5Addr = sgwS5Addr; |
| 477 } |
| 478 |
| 479 void |
| 480 EpcPgwApplication::AddUe (uint64_t imsi) |
| 481 { |
| 482 NS_LOG_FUNCTION (this << imsi); |
| 483 Ptr<UeInfo> ueInfo = Create<UeInfo> (); |
| 484 m_ueInfoByImsiMap[imsi] = ueInfo; |
| 485 } |
| 486 |
| 487 void |
| 488 EpcPgwApplication::SetUeAddress (uint64_t imsi, Ipv4Address ueAddr) |
| 489 { |
| 490 NS_LOG_FUNCTION (this << imsi << ueAddr); |
| 491 std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi
); |
| 492 NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI" << imsi);· |
| 493 ueit->second->SetUeAddr (ueAddr); |
| 494 m_ueInfoByAddrMap[ueAddr] = ueit->second; |
| 495 } |
| 496 |
| 497 void |
| 498 EpcPgwApplication::SetUeAddress6 (uint64_t imsi, Ipv6Address ueAddr) |
| 499 { |
| 500 NS_LOG_FUNCTION (this << imsi << ueAddr); |
| 501 std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi
); |
| 502 NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);· |
| 503 m_ueInfoByAddrMap6[ueAddr] = ueit->second; |
| 504 ueit->second->SetUeAddr6 (ueAddr); |
| 505 } |
| 506 |
| 507 } // namespace ns3 |
OLD | NEW |