diff --git a/src/lte/model/epc-sgw-pgw-application.cc b/src/lte/model/epc-sgw-pgw-application.cc index bd1345786..c9528e302 100644 --- a/src/lte/model/epc-sgw-pgw-application.cc +++ b/src/lte/model/epc-sgw-pgw-application.cc @@ -26,6 +26,7 @@ #include "ns3/ipv4.h" #include "ns3/inet-socket-address.h" #include "ns3/epc-gtpu-header.h" +#include "ns3/abort.h" namespace ns3 { @@ -33,25 +34,24 @@ NS_LOG_COMPONENT_DEFINE ("EpcSgwPgwApplication"); ///////////////////////// -// EnbInfo +// UeInfo ///////////////////////// -EpcSgwPgwApplication::EnbInfo::EnbInfo () - : m_teidCounter (0) +EpcSgwPgwApplication::UeInfo::UeInfo () { NS_LOG_FUNCTION (this); } -uint32_t -EpcSgwPgwApplication::EnbInfo::AddBearer (Ptr tft) +void +EpcSgwPgwApplication::UeInfo::AddBearer (Ptr tft, uint32_t teid) { - NS_LOG_FUNCTION (this << tft); - return m_tftClassifier.Add (tft); + NS_LOG_FUNCTION (this << tft << teid); + return m_tftClassifier.Add (tft, teid); } uint32_t -EpcSgwPgwApplication::EnbInfo::Classify (Ptr p) +EpcSgwPgwApplication::UeInfo::Classify (Ptr p) { NS_LOG_FUNCTION (this << p); // we hardcode DOWNLINK direction since the PGW is espected to @@ -60,6 +60,17 @@ EpcSgwPgwApplication::EnbInfo::Classify (Ptr p) return m_tftClassifier.Classify (p, LteTft::DOWNLINK); } +Ipv4Address +EpcSgwPgwApplication::UeInfo::GetEnbAddr () +{ + return m_enbAddr; +} + +void +EpcSgwPgwApplication::UeInfo::SetEnbAddr (Ipv4Address enbAddr) +{ + m_enbAddr = enbAddr; +} ///////////////////////// // EpcSgwPgwApplication @@ -79,7 +90,8 @@ EpcSgwPgwApplication::GetTypeId (void) EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr tunDevice, const Ptr s1uSocket) : m_s1uSocket (s1uSocket), m_tunDevice (tunDevice), - m_gtpuUdpPort (2152) // fixed by the standard + m_gtpuUdpPort (2152), // fixed by the standard + m_teidCount (0) { NS_LOG_FUNCTION (this << tunDevice << s1uSocket); m_s1uSocket->SetRecvCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromS1uSocket, this)); @@ -96,11 +108,24 @@ uint32_t EpcSgwPgwApplication::ActivateS1Bearer (Ipv4Address ueAddr, Ipv4Address enbAddr, Ptr tft) { NS_LOG_FUNCTION (this << ueAddr << enbAddr << tft); - // side effect: add entry if not exists - m_ueAddrEnbAddrMap[ueAddr] = enbAddr; - // side effect: create new EnbInfo if it does not exist - uint32_t teid = m_enbInfoMap[enbAddr].AddBearer (tft); + // simple sanity check. If you ever need more than 4M teids + // throughout your simulation, you'll need to implement a smarter teid + // management algorithm. + NS_ABORT_IF (m_teidCount == 0xFFFFFFFF); + uint32_t teid = ++m_teidCount; + + std::map::iterator it = m_ueInfoMap.find (ueAddr); + if (it == m_ueInfoMap.end ()) + { + // UE unknown, creating new entry + std::pair::iterator, bool> ret; + ret = m_ueInfoMap.insert (std::pair (ueAddr, UeInfo ())); + it = ret.first; + it->second.SetEnbAddr (enbAddr); + } + + it->second.AddBearer (tft, teid); return teid; } @@ -116,30 +141,28 @@ EpcSgwPgwApplication::RecvFromTunDevice (Ptr packet, const Address& sour Ipv4Address ueAddr = ipv4Header.GetDestination (); NS_LOG_LOGIC ("packet addressed to UE " << ueAddr); - // find corresponding eNB address - std::map::iterator it1 = m_ueAddrEnbAddrMap.find (ueAddr); - if (it1 == m_ueAddrEnbAddrMap.end ()) + // find corresponding UeInfo address + std::map::iterator it = m_ueInfoMap.find (ueAddr); + if (it == m_ueInfoMap.end ()) { - NS_LOG_WARN ("could not find corresponding eNB for UE address " << ueAddr) ; + NS_LOG_WARN ("unknown UE address " << ueAddr) ; } else { - Ipv4Address enbAddr = it1->second; - // lookup into TFT classifier for that eNB - std::map::iterator it2 = m_enbInfoMap.find (enbAddr); - NS_ASSERT (it2 != m_enbInfoMap.end ()); - uint32_t teid = it2->second.Classify (packet); + Ipv4Address enbAddr = it->second.GetEnbAddr (); + uint32_t teid = it->second.Classify (packet); if (teid == 0) { - NS_LOG_WARN ("no matching TEID for this packet"); + NS_LOG_WARN ("no matching bearer for this packet"); } else { SendToS1uSocket (packet, enbAddr, teid); } } - // there is no reason why we should notify the Gi TUN - // VirtualNetDevice that he failed to send the packet + // there is no reason why we should notify the TUN + // VirtualNetDevice that he failed to send the packet: if we receive + // any bogus packet, it will just be silently discarded. const bool succeeded = true; return succeeded; } diff --git a/src/lte/model/epc-sgw-pgw-application.h b/src/lte/model/epc-sgw-pgw-application.h index af6860597..105869c0d 100644 --- a/src/lte/model/epc-sgw-pgw-application.h +++ b/src/lte/model/epc-sgw-pgw-application.h @@ -130,36 +130,47 @@ private: /** - * store info for each eNB connected to this SGW - * + * store info for each UE connected to this SGW */ - class EnbInfo + class UeInfo { public: - EnbInfo (); + UeInfo (); /** * * \param tft the Traffic Flow Template of the new bearer to be added - * - * \return the TEID of the newly added bearer + * \param teid the TEID of the new bearer */ - uint32_t AddBearer (Ptr tft); - + void AddBearer (Ptr tft, uint32_t teid); /** * * * \param p the IP packet from the internet to be classified * - * \return the corresponding TEID > 0 if matched, or 0 if no match + * \return the corresponding bearer ID > 0 identifying the bearer + * among all the bearers of this UE; returns 0 if no bearers + * matches with the previously declared TFTs */ uint32_t Classify (Ptr p); + /** + * \return the address of the eNB to which the UE is connected + */ + Ipv4Address GetEnbAddr (); + + /** + * set the address of the eNB to which the UE is connected + * + * \param addr the address of the eNB + */ + void SetEnbAddr (Ipv4Address addr); + private: - uint32_t m_teidCounter; EpsTftClassifier m_tftClassifier; + Ipv4Address m_enbAddr; }; @@ -175,21 +186,17 @@ private: Ptr m_tunDevice; /** - * Map telling for each UE address what is the corresponding eNB address + * Map telling for each UE address the corresponding UE info */ - std::map m_ueAddrEnbAddrMap; - - /** - * Map telling for each eNB address the corresponding eNB info (TFT - * classifier, etc.) - */ - std::map m_enbInfoMap; + std::map m_ueInfoMap; /** * UDP port to be used for GTP */ uint16_t m_gtpuUdpPort; + uint32_t m_teidCount; + }; } //namespace ns3 diff --git a/src/lte/model/eps-tft-classifier.cc b/src/lte/model/eps-tft-classifier.cc index cc7092f0d..30b4c3b7a 100644 --- a/src/lte/model/eps-tft-classifier.cc +++ b/src/lte/model/eps-tft-classifier.cc @@ -28,7 +28,6 @@ #include "eps-tft-classifier.h" #include "lte-tft.h" -#include "ns3/abort.h" #include "ns3/log.h" #include "ns3/packet.h" #include "ns3/ipv4-header.h" @@ -42,20 +41,19 @@ NS_LOG_COMPONENT_DEFINE ("EpsTftClassifier"); namespace ns3 { EpsTftClassifier::EpsTftClassifier () - : m_tftCount (0) { NS_LOG_FUNCTION (this); } -uint32_t -EpsTftClassifier::Add (Ptr tft) +void +EpsTftClassifier::Add (Ptr tft, uint32_t id) { NS_LOG_FUNCTION (this << tft); - // simple sanity check. If you ever need more than 4M TFTs within a same classifiers, you'll need to implement a smarter id management algorithm. - NS_ABORT_IF (m_tftCount == 0xFFFFFFFF); - ++m_tftCount; - m_tftMap[m_tftCount] = tft; - return m_tftCount; + + m_tftMap[id] = tft; + + // simple sanity check: there shouldn't be more than 16 bearers (hence TFTs) per UE + NS_ASSERT (m_tftMap.size () <= 16); } void diff --git a/src/lte/model/eps-tft-classifier.h b/src/lte/model/eps-tft-classifier.h index a9b64e9fa..f054be339 100644 --- a/src/lte/model/eps-tft-classifier.h +++ b/src/lte/model/eps-tft-classifier.h @@ -51,9 +51,8 @@ public: * * \param tft the TFT to be added * - * \return the unique identifier of the added TFT within this Classifier instance */ - uint32_t Add (Ptr tft); + void Add (Ptr tft, uint32_t id); /** * delete an existing TFT from the classifier @@ -75,7 +74,6 @@ public: protected: std::map > m_tftMap; - uint32_t m_tftCount; }; diff --git a/src/lte/test/test-eps-tft-classifier.cc b/src/lte/test/test-eps-tft-classifier.cc index 66624a6bb..3035e364e 100644 --- a/src/lte/test/test-eps-tft-classifier.cc +++ b/src/lte/test/test-eps-tft-classifier.cc @@ -159,7 +159,7 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite () pf1_1_2.localMask.Set (0xFFFFFF00); tft1_1->Add (pf1_1_2); - c1->Add (tft1_1); + c1->Add (tft1_1, 1); @@ -175,7 +175,7 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite () pf1_2_2.localPortEnd = 3489; tft1_2->Add (pf1_2_2); - c1->Add (tft1_2); + c1->Add (tft1_2, 2); // ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id @@ -211,7 +211,7 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite () /////////////////////////// Ptr c2 = Create (); - c2->Add (LteTft::Default ()); + c2->Add (LteTft::Default (), 1); // ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id @@ -247,9 +247,9 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite () /////////////////////////////////////////// Ptr c3 = Create (); - c3->Add (LteTft::Default ()); - c3->Add (tft1_1); - c3->Add (tft1_2); + c3->Add (LteTft::Default (), 1); + c3->Add (tft1_1, 2); + c3->Add (tft1_2, 3); // ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id