--- a/src/lte/doc/source/figures/nas-activate-dedicated-bearer.seqdiag Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/doc/source/figures/nas-activate-dedicated-bearer.seqdiag Wed Nov 28 11:37:28 2012 +0100
@@ -10,7 +10,7 @@
EpcSgwPgwApplication => EpcSgwPgwApplication [label="Create GTP-U tunnel endpoint"];
}
EpcHelper => EpcEnbApplication [label="ErabSetupRequest(TEID, IMSI)"] {
- EpcEnbApplication => LteEnbRrc [label="RadioBearerSetupRequest (IMSI)", return="RadioBearerSetupCompleted (RNTI, LCID)"] {
+ EpcEnbApplication => LteEnbRrc [label="RadioBearerSetupRequest (IMSI)", return="S1BearerSetupRequest (RNTI, LCID)"] {
LteEnbRrc => LteUeRrc [label="RRC connection reconfiguration"];
}
EpcEnbApplication -> EpcEnbApplication [label="Create GTP-U tunnel endpoint (TEID)"];
--- a/src/lte/doc/source/figures/nas-attach.seqdiag Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/doc/source/figures/nas-attach.seqdiag Wed Nov 28 11:37:28 2012 +0100
@@ -1,34 +1,30 @@
diagram {
- SimProgram; LteHelper; LteUeNetDevice; EpcUeNas; LteUeRrc; LteEnbRrc; EpcEnbApplication; EpcSgwPgwApplication; EpcHelper;
+ EpcUeNas; LteUeRrc; LteEnbRrc; EpcEnbApplication; EpcSgwPgwApplication; EpcMme;
+
- SimProgram -> LteHelper [label="Attach (ueDevice, enbDevice)"];
- LteHelper -> EpcUeNas [label="Connect (eNB)"] {
- EpcUeNas -> LteUeRrc [label="ForceCampedOnEnb (CellID)"];
- EpcUeNas => LteUeRrc [label="Connect"] {
- LteUeRrc => LteEnbRrc [label="Connection Request (IMSI)"] {
- === RRC connection establishment ===
- LteEnbRrc -> LteEnbRrc [label="store IMSI<->RNTI mapping"];
- }
- }
- }
-
- EpcUeNas => EpcHelper [label="Attach (UeDevice, EnbDevice)"] {
- EpcHelper -> EpcHelper [label="store UeDevice <-> EnbDevice mapping"]
- }
- EpcUeNas => EpcHelper [label="ActivateEpsBearer (UeDevice, IMSI, EpsBearer (NGBR_VIDEO_TCP_DEFAULT), Tft::Default)"] {
- EpcHelper => EpcSgwPgwApplication [label="ActivateS1Bearer (UE IP, eNB IP, IMSI, Tft::Default)", return="TEID"] {
+ EpcUeNas -> LteUeRrc [label="ForceCampedOnEnb (CellID)"];
+ EpcUeNas => LteUeRrc [label="Connect (S-TMSI, InitialNasMessage = EMM ATTACH REQUEST + ESM PDN CONNECTIVITY REQUEST)"] {
+ LteUeRrc -> LteEnbRrc [label="RRC Connection Request (S-TMSI + InitialNasMessage)"]
+ === RRC connection establishment ===
+ LteUeRrc <- LteEnbRrc [label="RNTI"]
+ LteEnbRrc -> EpcEnbApplication [label="UL NAS fwd (initial UE message)"]
+ EpcEnbApplication -> EpcMme [label="S1-AP INITIAL UE MESSAGE (eNB UE S1 id = RNTI, S-TMSI, EGCI, NAS PDU)" return="InitialContextSetup (IMSI, RNTI, ERABs to be setup)"]
+ EpcMme -> EpcMme [label="store IMSI->eNB UE id (RNTI) mapping"]
+ EpcMme -> EpcSgwPgwApplication [label="CreateSessionRequest (IMSI, EGCI, BearerContext)"] {
EpcSgwPgwApplication => EpcSgwPgwApplication [label="Store UE IP<->eNB IP mapping"];
EpcSgwPgwApplication => EpcSgwPgwApplication [label="Create GTP-U tunnel endpoint"];
}
- EpcHelper => EpcEnbApplication [label="ErabSetupRequest(TEID, IMSI)"] {
- EpcEnbApplication => LteEnbRrc [label="RadioBearerSetupRequest (IMSI)", return="RadioBearerSetupCompleted (RNTI, LCID)"] {
- LteEnbRrc => LteUeRrc [label="RRC connection reconfiguration"];
- }
+ EpcMme <- EpcSgwPgwApplication [label="CreateSessionResponse (SGW-FQ-CSID, BearerContext)"]
+ EpcMme => EpcEnbApplication [label="InitialContextSetupRequest(TEID, IMSI, RNTI, ERABs to be setup (incl. TEIDs))"] {
EpcEnbApplication -> EpcEnbApplication [label="Create GTP-U tunnel endpoint (TEID)"];
EpcEnbApplication -> EpcEnbApplication [label="store TEID<->(RNTI,LCID) mapping"];
- }
+ EpcEnbApplication => LteEnbRrc [label="RadioBearerSetupRequest (RNTI, QoS params, EBIs)", return="S1BearerSetupRequest (RNTI, LCID)"] {
+ LteEnbRrc -> LteUeRrc [label="RRC connection reconfiguration"];
+ }
+ }
}
-
+ EpcUeNas <- EpcMme [label="EMM ATTACH COMPLETE + ESM ACTIVATE DEFAULT EPS BEARER REQUEST"]
+ EpcUeNas -> EpcMme [label="ESM ACTIVATE DEFAULT EPS BEARER RESPONSE"]
}
--- a/src/lte/helper/epc-helper.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/helper/epc-helper.cc Wed Nov 28 11:37:28 2012 +0100
@@ -35,7 +35,9 @@
#include <ns3/lte-enb-rrc.h>
#include <ns3/epc-x2.h>
#include <ns3/lte-enb-net-device.h>
-
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/epc-mme.h>
+#include <ns3/epc-ue-nas.h>
namespace ns3 {
@@ -94,6 +96,10 @@
// connect SgwPgwApplication and virtual net device for tunneling
m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp));
+ // Create MME and connect with SGW via S11 interface
+ m_mme = CreateObject<EpcMme> ();
+ m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ());
+ m_sgwPgwApp->SetS11SapMme (m_mme->GetS11SapMme ());
}
EpcHelper::~EpcHelper ()
@@ -138,9 +144,9 @@
void
-EpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice)
+EpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId)
{
- NS_LOG_FUNCTION (this << enb << lteEnbNetDevice);
+ NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId);
NS_ASSERT (enb == lteEnbNetDevice->GetNode ());
@@ -195,7 +201,7 @@
NS_LOG_INFO ("create EpcEnbApplication");
- Ptr<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbS1uSocket, sgwAddress);
+ Ptr<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbS1uSocket, sgwAddress, cellId);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
@@ -206,6 +212,10 @@
Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
enb->AggregateObject (x2);
+ NS_LOG_INFO ("connect S1-AP interface");
+ m_mme->AddEnb (cellId, enbAddress, enbApp->GetS1apSapEnb ());
+ m_sgwPgwApp->AddEnb (cellId, enbAddress, sgwAddress);
+ enbApp->SetS1apSapMme (m_mme->GetS1apSapMme ());
}
@@ -269,56 +279,39 @@
void
-EpcHelper::AttachUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<NetDevice> enbDevice)
+EpcHelper::AddUe (Ptr<NetDevice> ueDevice, uint64_t imsi)
{
- NS_LOG_FUNCTION (this << ueLteDevice << enbDevice);
+ NS_LOG_FUNCTION (this << imsi << ueDevice );
+
+ m_mme->AddUe (imsi);
+ m_sgwPgwApp->AddUe (imsi);
+
- m_imsiEnbDeviceMap[imsi] = enbDevice;
}
void
-EpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer)
+EpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer)
{
- std::map<uint64_t, Ptr<NetDevice> >::iterator it = m_imsiEnbDeviceMap.find (imsi);
- NS_ASSERT_MSG (it != m_imsiEnbDeviceMap.end (), "no eNB found for this IMSI, did you attach it before?");
- Ptr<NetDevice> enbDevice = it->second;
- Ptr<Node> ueNode = ueLteDevice->GetNode ();
+ NS_LOG_FUNCTION (this << ueDevice << imsi);
+
+ // we now retrieve the IPv4 address of the UE and notify it to the SGW;
+ // we couldn't do it before since address assignment is triggered by
+ // the user simulation program, rather than done by the EPC
+ Ptr<Node> ueNode = ueDevice->GetNode ();
Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated");
- int32_t interface = ueIpv4->GetInterfaceForDevice (ueLteDevice);
+ int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice);
NS_ASSERT (interface >= 0);
NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1);
Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal ();
- NS_LOG_LOGIC (" UE IP address: " << ueAddr);
-
- // NOTE: unlike ueLteDevice, enbDevice is NOT an Ipv4 enabled
- // device. In fact we are interested in the S1 device of the eNB.
- // We find it by relying on the assumption that the S1 device is the
- // only Ipv4 enabled device of the eNB besides the localhost interface.
- Ptr<Node> enbNode = enbDevice->GetNode ();
- NS_ASSERT (enbNode != 0);
- Ptr<Ipv4> enbIpv4 = enbNode->GetObject<Ipv4> ();
- NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB: " << enbIpv4->GetNInterfaces ());
- // two ifaces total: loopback + the S1-U interface
- NS_ASSERT (enbIpv4->GetNInterfaces () >= 2);
- NS_ASSERT (ueIpv4->GetNAddresses (1) == 1);
- // iface index 0 is loopback, index 1 is the S1-U interface
- Ipv4Address enbAddr = enbIpv4->GetAddress (1, 0).GetLocal ();
- NS_LOG_LOGIC (" ENB IP address: " << enbAddr);
-
- // setup S1 bearer at EpcSgwPgwApplication
- uint32_t teid = m_sgwPgwApp->ActivateS1Bearer (ueAddr, enbAddr, tft);
-
- // setup S1 bearer at EpcEnbApplication
- NS_LOG_LOGIC ("enb: " << enbNode << ", enb->GetApplication (0): " << enbNode->GetApplication (0));
- NS_ASSERT (enbNode->GetNApplications () == 1);
- Ptr<Application> app = enbNode->GetApplication (0);
- NS_ASSERT (app != 0);
- Ptr<EpcEnbApplication> epcEnbApp = app->GetObject<EpcEnbApplication> ();
- NS_ASSERT (epcEnbApp != 0);
- epcEnbApp->ErabSetupRequest (teid, imsi, bearer);
+ NS_LOG_LOGIC (" UE IP address: " << ueAddr); m_sgwPgwApp->SetUeAddress (imsi, ueAddr);
-
+ m_mme->AddBearer (imsi, tft, bearer);
+ Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ if (ueLteDevice)
+ {
+ ueLteDevice->GetNas ()->ActivateEpsBearer (bearer, tft);
+ }
}
--- a/src/lte/helper/epc-helper.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/helper/epc-helper.h Wed Nov 28 11:37:28 2012 +0100
@@ -35,6 +35,7 @@
class VirtualNetDevice;
class EpcSgwPgwApplication;
class EpcX2;
+class EpcMme;
/**
* \brief Helper class to handle the creation of the EPC entities and protocols.
@@ -69,18 +70,17 @@
* \param enbNode the previosuly created eNB node which is to be
* added to the EPC
* \param lteEnbNetDevice the LteEnbNetDevice of the eNB node
+ * \param cellId ID of the eNB
*/
- void AddEnb (Ptr<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice);
+ void AddEnb (Ptr<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId);
/**
- * Simplified UE Attachment somewhat equivalent to NAS EMM Attach
- * Request + ECM PDN Connectivity Request
+ * Notify the EPC of the existance of a new UE which might attach at a later time
*
* \param ueLteDevice the UE device to be attached
* \param imsi the unique identifier of the UE
- * \param enbDevice the eNB to which the UE is currently connected
*/
- void AttachUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<NetDevice> enbDevice);
+ void AddUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi);
/**
* Add an X2 interface between two eNB
@@ -146,7 +146,7 @@
Ptr<Node> m_sgwPgw;
Ptr<EpcSgwPgwApplication> m_sgwPgwApp;
Ptr<VirtualNetDevice> m_tunDevice;
-
+ Ptr<EpcMme> m_mme;
/**
* S1-U interfaces
--- a/src/lte/helper/lte-helper.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/helper/lte-helper.cc Wed Nov 28 11:37:28 2012 +0100
@@ -418,7 +418,7 @@
if (m_epcHelper != 0)
{
NS_LOG_INFO ("adding this eNB to the EPC");
- m_epcHelper->AddEnb (n, dev);
+ m_epcHelper->AddEnb (n, dev, dev->GetCellId ());
Ptr<EpcEnbApplication> enbApp = n->GetApplication (0)->GetObject<EpcEnbApplication> ();
NS_ASSERT_MSG (enbApp != 0, "cannot retrieve EpcEnbApplication");
@@ -480,8 +480,6 @@
}
Ptr<EpcUeNas> nas = CreateObject<EpcUeNas> ();
- nas->SetEpcHelper (m_epcHelper);
-
// connect SAPs
nas->SetAsSapProvider (rrc->GetAsSapProvider ());
rrc->SetAsSapUser (nas->GetAsSapUser ());
@@ -511,6 +509,11 @@
dlPhy->SetLtePhyDlHarqFeedbackCallback (MakeCallback (&LteUePhy::ReceiveLteDlHarqFeedback, phy));
nas->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
+ if (m_epcHelper != 0)
+ {
+ m_epcHelper->AddUe (dev, dev->GetImsi ());
+ }
+
dev->Start ();
return dev;
@@ -534,8 +537,16 @@
//enbRrc->SetCellId (enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
+
Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
- ueNas->Connect (enbDevice);
+ ueNas->Connect (enbLteDevice->GetCellId (), enbLteDevice->GetDlEarfcn ());
+
+ if (m_epcHelper != 0)
+ {
+ // activate default EPS bearer
+ m_epcHelper->ActivateEpsBearer (ueDevice, ueLteDevice->GetImsi (), EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
+ }
// tricks needed for the simplified LTE-only simulations
if (m_epcHelper == 0)
@@ -594,8 +605,8 @@
NS_ASSERT_MSG (m_epcHelper != 0, "dedicated EPS bearers cannot be set up when EPC is not used");
- ueDevice->GetObject<LteUeNetDevice> ()->ActivateDedicatedEpsBearer (bearer, tft);
-
+ uint64_t imsi = ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
+ m_epcHelper->ActivateEpsBearer (ueDevice, imsi, tft, bearer);
}
void
--- a/src/lte/model/epc-enb-application.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-enb-application.cc Wed Nov 28 11:37:28 2012 +0100
@@ -74,19 +74,24 @@
m_lteSocket = 0;
m_s1uSocket = 0;
delete m_s1SapProvider;
+ delete m_s1apSapEnb;
}
-EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress)
+EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress, uint16_t cellId)
: m_lteSocket (lteSocket),
m_s1uSocket (s1uSocket),
m_sgwAddress (sgwAddress),
- m_gtpuUdpPort (2152) // fixed by the standard
+ m_gtpuUdpPort (2152), // fixed by the standard
+ m_s1SapUser (0),
+ m_s1apSapMme (0),
+ m_cellId (cellId)
{
NS_LOG_FUNCTION (this << lteSocket << s1uSocket << sgwAddress);
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromS1uSocket, this));
m_lteSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this));
m_s1SapProvider = new MemberEpcEnbS1SapProvider<EpcEnbApplication> (this);
+ m_s1apSapEnb = new MemberEpcS1apSapEnb<EpcEnbApplication> (this);
}
@@ -110,6 +115,19 @@
}
void
+EpcEnbApplication::SetS1apSapMme (EpcS1apSapMme * s)
+{
+ m_s1apSapMme = s;
+}
+
+
+EpcS1apSapEnb*
+EpcEnbApplication::GetS1apSapEnb ()
+{
+ return m_s1apSapEnb;
+}
+
+void
EpcEnbApplication::ErabSetupRequest (uint32_t teid, uint64_t imsi, EpsBearer bearer)
{
NS_LOG_FUNCTION (this << teid << imsi);
@@ -140,6 +158,28 @@
NS_LOG_FUNCTION (this);
// side effect: create entry if not exist
m_imsiRntiMap[imsi] = rnti;
+ m_s1apSapMme->InitialUeMessage (imsi, rnti, imsi, m_cellId);
+}
+
+
+void
+EpcEnbApplication::DoInitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
+{
+ NS_LOG_FUNCTION (this);
+
+ for (std::list<EpcS1apSapEnb::ErabToBeSetupItem>::iterator it = erabToBeSetupList.begin ();
+ it != erabToBeSetupList.end ();
+ ++it)
+ {
+ ErabSetupRequest (it->sgwTeid, mmeUeS1Id, it->erabLevelQosParameters);
+ }
+}
+
+void
+EpcEnbApplication::DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
+{
+ NS_LOG_FUNCTION (this);
+ NS_FATAL_ERROR ("not implemented");
}
void
--- a/src/lte/model/epc-enb-application.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-enb-application.h Wed Nov 28 11:37:28 2012 +0100
@@ -33,6 +33,7 @@
#include <ns3/application.h>
#include <ns3/eps-bearer.h>
#include <ns3/epc-enb-s1-sap.h>
+#include <ns3/epc-s1ap-sap.h>
#include <map>
namespace ns3 {
@@ -49,7 +50,7 @@
{
friend class MemberEpcEnbS1SapProvider<EpcEnbApplication>;
-
+ friend class MemberEpcS1apSapEnb<EpcEnbApplication>;
// inherited from Object
@@ -69,9 +70,9 @@
* \param s1uSocket the socket to be used to send/receive packets
* to/from the S1-U interface connected with the SGW
* \param sgwAddress the IPv4 address at which this eNB will be able to reach its SGW
- *
+ * \param cellId the identifier of the enb
*/
- EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress);
+ EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress, uint16_t cellId);
/**
* Destructor
@@ -94,6 +95,19 @@
EpcEnbS1SapProvider* GetS1SapProvider ();
/**
+ * Set the MME side of the S1-AP SAP
+ *
+ * \param s the MME side of the S1-AP SAP
+ */
+ void SetS1apSapMme (EpcS1apSapMme * s);
+
+ /**
+ *
+ * \return the ENB side of the S1-AP SAP
+ */
+ EpcS1apSapEnb* GetS1apSapEnb ();
+
+ /**
* This method is triggered after the eNB received
* a S1-AP message of type E-RAB Setup Request by the MME and will
* trigger the corresponding RadioBearer creation
@@ -136,10 +150,14 @@
private:
- // S1 SAP provider methods
+ // ENB S1 SAP provider methods
void DoS1BearerSetupRequest (EpcEnbS1SapProvider::S1BearerSetupRequestParameters params);
void DoInitialUeMessage (uint64_t imsi, uint16_t rnti);
+ // S1-AP SAP ENB methods
+ void DoInitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList);
+ void DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList);
+
/**
* Send a packet to the UE via the LTE radio interface of the eNB
*
@@ -210,6 +228,17 @@
*/
EpcEnbS1SapUser* m_s1SapUser;
+ /**
+ * MME side of the S1-AP SAP
+ *
+ */
+ EpcS1apSapMme* m_s1apSapMme;
+
+ /**
+ * ENB side of the S1-AP SAP
+ *
+ */
+ EpcS1apSapEnb* m_s1apSapEnb;
/**
* UE context info
@@ -217,6 +246,8 @@
*/
std::map<uint64_t, uint16_t> m_imsiRntiMap;
+ uint16_t m_cellId;
+
};
} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-mme.cc Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include <ns3/fatal-error.h>
+#include <ns3/log.h>
+
+#include "epc-s1ap-sap.h"
+#include "epc-s11-sap.h"
+
+#include "epc-mme.h"
+
+NS_LOG_COMPONENT_DEFINE ("EpcMme");
+
+namespace ns3 {
+
+
+
+
+NS_OBJECT_ENSURE_REGISTERED (EpcMme);
+
+EpcMme::EpcMme ()
+ : m_s11SapSgw (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_s1apSapMme = new MemberEpcS1apSapMme<EpcMme> (this);
+ m_s11SapMme = new MemberEpcS11SapMme<EpcMme> (this);
+}
+
+
+EpcMme::~EpcMme ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+EpcMme::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_s1apSapMme;
+ delete m_s11SapMme;
+}
+
+TypeId
+EpcMme::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EpcMme")
+ .SetParent<Object> ()
+ .AddConstructor<EpcMme> ()
+ ;
+ return tid;
+}
+
+EpcS1apSapMme*
+EpcMme::GetS1apSapMme ()
+{
+ return m_s1apSapMme;
+}
+
+void
+EpcMme::SetS11SapSgw (EpcS11SapSgw * s)
+{
+ m_s11SapSgw = s;
+}
+
+EpcS11SapMme*
+EpcMme::GetS11SapMme ()
+{
+ return m_s11SapMme;
+}
+
+void
+EpcMme::AddEnb (uint16_t gci, Ipv4Address enbS1uAddr, EpcS1apSapEnb* enbS1apSap)
+{
+ NS_LOG_FUNCTION (this << gci << enbS1uAddr);
+ Ptr<EnbInfo> enbInfo = Create<EnbInfo> ();
+ enbInfo->gci = gci;
+ enbInfo->s1uAddr = enbS1uAddr;
+ enbInfo->s1apSapEnb = enbS1apSap;
+ m_enbInfoMap[gci] = enbInfo;
+}
+
+void
+EpcMme::AddUe (uint64_t imsi)
+{
+ NS_LOG_FUNCTION (this << imsi);
+ Ptr<UeInfo> ueInfo = Create<UeInfo> ();
+ ueInfo->imsi = imsi;
+ ueInfo->mmeUeS1Id = imsi;
+ m_ueInfoMap[imsi] = ueInfo;
+ ueInfo->bearerCounter = 0;
+}
+
+void
+EpcMme::AddBearer (uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer)
+{
+ NS_LOG_FUNCTION (this << imsi);
+ std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
+ NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
+ NS_ASSERT_MSG (it->second->bearerCounter < 11, "too many bearers already! " << it->second->bearerCounter);
+ BearerInfo bearerInfo;
+ bearerInfo.bearerId = ++(it->second->bearerCounter);
+ bearerInfo.tft = tft;
+ bearerInfo.bearer = bearer;
+ it->second->bearersToBeActivated.push_back (bearerInfo);
+}
+
+
+// S1-AP SAP MME forwarded methods
+
+void
+EpcMme::DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t gci)
+{
+ NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << imsi << gci);
+ std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
+ NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
+ it->second->cellId = gci;
+ std::list<EpcS11SapSgw::BearerContext> bearersToBeSetup;
+ for (std::list<BearerInfo>::iterator bit = it->second->bearersToBeActivated.begin ();
+ bit != it->second->bearersToBeActivated.end ();
+ ++bit)
+ {
+ EpcS11SapSgw::BearerContext bearerContext;
+ bearerContext.epsBearerId = bit->bearerId;
+ bearerContext.bearerLevelQos = bit->bearer;
+ bearerContext.tft = bit->tft;
+ bearersToBeSetup.push_back (bearerContext);
+ }
+ EpcS11Sap::Uli uli;
+ uli.gci = gci;
+ m_s11SapSgw->RecvCreateSessionRequest (imsi, uli, bearersToBeSetup);
+}
+
+void
+EpcMme::DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList)
+{
+ NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id);
+ NS_FATAL_ERROR ("unimplemented");
+}
+
+void
+EpcMme::DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
+{
+ NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << gci);
+ NS_FATAL_ERROR ("unimplemented");
+}
+
+
+// S11 SAP MME forwarded methods
+
+void
+EpcMme::DoRecvCreateSessionResponse (uint64_t imsi, std::list<EpcS11SapMme::BearerContext> bearerContextList)
+{
+ NS_LOG_FUNCTION (this << imsi);
+ std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList;
+ for (std::list<EpcS11SapMme::BearerContext>::iterator bit = bearerContextList.begin ();
+ bit != bearerContextList.end ();
+ ++bit)
+ {
+ EpcS1apSapEnb::ErabToBeSetupItem erab;
+ erab.erabId = bit->epsBearerId;
+ erab.erabLevelQosParameters = bit->bearerLevelQos;
+ erab.transportLayerAddress = bit->sgwFteid.address;
+ erab.sgwTeid = bit->sgwFteid.teid;
+ erabToBeSetupList.push_back (erab);
+ }
+ std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
+ NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
+ uint16_t cellId = it->second->cellId;
+ uint16_t enbUeS1Id = it->second->enbUeS1Id;
+ uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
+ std::map<uint16_t, Ptr<EnbInfo> >::iterator jt = m_enbInfoMap.find (cellId);
+ NS_ASSERT_MSG (jt != m_enbInfoMap.end (), "could not find any eNB with CellId " << cellId);
+ jt->second->s1apSapEnb->InitialContextSetupRequest (mmeUeS1Id, enbUeS1Id, erabToBeSetupList);
+}
+
+
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-mme.h Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef EPC_MME_H
+#define EPC_MME_H
+
+#include <ns3/object.h>
+#include <ns3/epc-s1ap-sap.h>
+#include <ns3/epc-s11-sap.h>
+
+#include <map>
+#include <list>
+
+namespace ns3 {
+
+class Node;
+class NetDevice;
+
+/**
+ * \brief This object implements the MME functionality.
+ *
+ */
+class EpcMme : public Object
+{
+
+ friend class MemberEpcS1apSapMme<EpcMme>;
+ friend class MemberEpcS11SapMme<EpcMme>;
+
+public:
+
+ /**
+ * Constructor
+ */
+ EpcMme ();
+
+ /**
+ * Destructor
+ */
+ virtual ~EpcMme ();
+
+ // inherited from Object
+ static TypeId GetTypeId (void);
+protected:
+ virtual void DoDispose ();
+
+public:
+
+
+ /**
+ *
+ * \return the MME side of the S1-AP SAP
+ */
+ EpcS1apSapMme* GetS1apSapMme ();
+
+ /**
+ * Set the SGW side of the S11 SAP
+ *
+ * \param s the SGW side of the S11 SAP
+ */
+ void SetS11SapSgw (EpcS11SapSgw * s);
+
+ /**
+ *
+ * \return the MME side of the S11 SAP
+ */
+ EpcS11SapMme* GetS11SapMme ();
+
+ /**
+ * Add a new ENB to the MME.
+ * \param imsi the unique identifier of the UE
+ * \param enbS1apSap the ENB side of the S1-AP SAP
+ */
+ void AddEnb (uint16_t egci, Ipv4Address enbS1UAddr, EpcS1apSapEnb* enbS1apSap);
+
+ /**
+ * Add a new UE to the MME. This is the equivalent of storing the UE
+ * credentials before the UE is ever turned on.
+ *
+ * \param imsi the unique identifier of the UE
+ */
+ void AddUe (uint64_t imsi);
+
+ /**
+ * Add an EPS bearer to the list of bearers to be activated for this
+ * UE. The bearer will be activated when the UE enters the ECM
+ * connected state.
+ *
+ * \param imsi UE identifier
+ * \param tft traffic flow template of the bearer
+ * \param bearer QoS characteristics of the bearer
+ */
+ void AddBearer (uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer);
+
+
+private:
+
+ // S1-AP SAP MME forwarded methods
+ void DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi);
+ void DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList);
+ void DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList);
+
+
+ // S11 SAP MME forwarded methods
+ void DoRecvCreateSessionResponse (uint64_t imsi, std::list<EpcS11SapMme::BearerContext>);
+
+ /**
+ * Hold info on an EPS bearer to be activated
+ *
+ */
+ struct BearerInfo
+ {
+ Ptr<EpcTft> tft;
+ EpsBearer bearer;
+ uint8_t bearerId;
+ };
+
+ /**
+ * Hold info on a UE
+ *
+ */
+ struct UeInfo : public SimpleRefCount<UeInfo>
+ {
+ uint64_t mmeUeS1Id;
+ uint16_t enbUeS1Id;
+ uint64_t imsi;
+ uint16_t cellId;
+ std::list<BearerInfo> bearersToBeActivated;
+ uint16_t bearerCounter;
+ };
+
+ /**
+ * UeInfo stored by IMSI
+ *
+ */
+ std::map<uint64_t, Ptr<UeInfo> > m_ueInfoMap;
+
+ /**
+ * Hold info on a ENB
+ *
+ */
+ struct EnbInfo : public SimpleRefCount<EnbInfo>
+ {
+ uint16_t gci;
+ Ipv4Address s1uAddr;
+ EpcS1apSapEnb* s1apSapEnb;
+ };
+
+ /**
+ * EnbInfo stored by EGCI
+ *
+ */
+ std::map<uint16_t, Ptr<EnbInfo> > m_enbInfoMap;
+
+
+
+
+ EpcS1apSapMme* m_s1apSapMme;
+
+ EpcS11SapMme* m_s11SapMme;
+ EpcS11SapSgw* m_s11SapSgw;
+
+};
+
+
+
+
+} // namespace ns3
+
+#endif // EPC_MME_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-s11-sap.cc Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "epc-s11-sap.h"
+
+namespace ns3 {
+
+EpcS11Sap::~EpcS11Sap ()
+{
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-s11-sap.h Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.cat>
+ */
+
+#ifndef EPC_S11_SAP_H
+#define EPC_S11_SAP_H
+
+#include <ns3/address.h>
+#include <ns3/ptr.h>
+#include <ns3/object.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/epc-tft.h>
+#include <list>
+
+namespace ns3 {
+
+class EpcS11Sap
+{
+public:
+
+ virtual ~EpcS11Sap ();
+
+ /**
+ * Fully-qualified TEID, see 3GPP TS 29.274 section 8.22
+ *
+ */
+ struct Fteid
+ {
+ uint32_t teid;
+ Ipv4Address address;
+ };
+
+ /**
+ * TS 29.274 8.21 User Location Information (ULI)
+ *
+ */
+ struct Uli
+ {
+ uint16_t gci;
+ };
+
+
+};
+
+/**
+ * \ingroup lte
+ *
+ * MME side of the S11 Service Access Point (SAP), provides the MME
+ * methods to be called when an S11 message is received by the MME.
+ */
+ class EpcS11SapMme : public EpcS11Sap
+{
+public:
+
+ /**
+ * 3GPP TS 29.274 version 8.3.1 Release 8 section 8.28
+ *
+ */
+ struct BearerContext
+ {
+
+ EpcS11Sap::Fteid sgwFteid;
+ uint8_t epsBearerId;
+ EpsBearer bearerLevelQos;
+ Ptr<EpcTft> tft;
+ };
+
+ virtual void RecvCreateSessionResponse (uint64_t imsi, std::list<BearerContext> bearerContextList) = 0;
+
+};
+
+/**
+ * \ingroup lte
+ *
+ * SGW side of the S11 Service Access Point (SAP), provides the SGW
+ * methods to be called when an S11 message is received by the SGW.
+ */
+class EpcS11SapSgw : public EpcS11Sap
+{
+public:
+
+ struct BearerContext
+ {
+
+ EpcS11Sap::Fteid sgwFteid;
+ uint8_t epsBearerId;
+ EpsBearer bearerLevelQos;
+ Ptr<EpcTft> tft;
+ };
+
+ /**
+ *
+ *
+ * \param imsi
+ * \param uli theoretically, the User Location Information (ULI) which
+ * includes the EGCI. In practice, we use the Cell Id.
+ * \param bearersToBeSetup default bearer + eventual other bearers
+ * to be setup
+ */
+ virtual void RecvCreateSessionRequest (uint64_t imsi, Uli uli, std::list<BearerContext> bearersToBeSetup) = 0;
+
+
+ /**
+ *
+ *
+ * \param imsi not included in the specs, we add it for simplicity.
+ * \param uli theoretically, the User Location Information (ULI) which
+ * includes the EGCI. In practice, we use the Cell Id.
+ * \param bearersToBeSetup
+ */
+ virtual void ModifyBearerRequest (uint64_t mei, Uli uli, std::list<BearerContext> bearersToBeSetup) = 0;
+
+};
+
+
+
+
+
+
+
+/**
+ * Template for the implementation of the EpcS11SapMme as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberEpcS11SapMme : public EpcS11SapMme
+{
+public:
+ MemberEpcS11SapMme (C* owner);
+
+ // inherited from EpcS11SapMme
+ void RecvCreateSessionResponse (uint64_t imsi, std::list<BearerContext>);
+
+private:
+ MemberEpcS11SapMme ();
+ C* m_owner;
+};
+
+template <class C>
+MemberEpcS11SapMme<C>::MemberEpcS11SapMme (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberEpcS11SapMme<C>::MemberEpcS11SapMme ()
+{
+}
+
+template <class C>
+void MemberEpcS11SapMme<C>::RecvCreateSessionResponse (uint64_t imsi, std::list<BearerContext> bearerContextList)
+{
+ m_owner->DoRecvCreateSessionResponse (imsi, bearerContextList);
+}
+
+
+
+
+
+/**
+ * Template for the implementation of the EpcS11SapSgw as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberEpcS11SapSgw : public EpcS11SapSgw
+{
+public:
+ MemberEpcS11SapSgw (C* owner);
+
+ // inherited from EpcS11SapSgw
+ virtual void RecvCreateSessionRequest (uint64_t imsi, Uli uli, std::list<BearerContext> bearersToBeSetup);
+ virtual void ModifyBearerRequest (uint64_t mei, Uli uli, std::list<BearerContext> bearersToBeSetup);
+
+private:
+ MemberEpcS11SapSgw ();
+ C* m_owner;
+};
+
+template <class C>
+MemberEpcS11SapSgw<C>::MemberEpcS11SapSgw (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberEpcS11SapSgw<C>::MemberEpcS11SapSgw ()
+{
+}
+
+template <class C>
+void MemberEpcS11SapSgw<C>::RecvCreateSessionRequest (uint64_t imsi, Uli uli, std::list<BearerContext> bearersToBeSetup)
+{
+ m_owner->DoRecvCreateSessionRequest (imsi, uli, bearersToBeSetup);
+}
+
+template <class C>
+void MemberEpcS11SapSgw<C>::ModifyBearerRequest (uint64_t mei, Uli uli, std::list<BearerContext> bearersToBeSetup)
+{
+ m_owner->DoModifyBearerRequest (mei, uli, bearersToBeSetup);
+}
+
+
+
+
+
+
+
+
+
+} //namespace ns3
+
+#endif /* EPC_S11_SAP_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-s1ap-sap.cc Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "epc-s1ap-sap.h"
+
+namespace ns3 {
+
+EpcS1apSap::~EpcS1apSap ()
+{
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-s1ap-sap.h Wed Nov 28 11:37:28 2012 +0100
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.cat>
+ */
+
+#ifndef EPC_S1AP_SAP_H
+#define EPC_S1AP_SAP_H
+
+#include <ns3/address.h>
+#include <ns3/ptr.h>
+#include <ns3/object.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/epc-tft.h>
+#include <list>
+
+
+namespace ns3 {
+
+class EpcS1apSap
+{
+public:
+ virtual ~EpcS1apSap ();
+
+};
+
+
+/**
+ * \ingroup lte
+ *
+ * MME side of the S1-AP Service Access Point (SAP), provides the MME
+ * methods to be called when an S1-AP message is received by the MME.
+ */
+class EpcS1apSapMme : public EpcS1apSap
+{
+public:
+
+ /**
+ *
+ * \param mmeUeS1Id in practice, we use the IMSI
+ * \param enbUeS1Id in practice, we use the RNTI
+ * \param s-tmsi in practice, the imsi
+ * \param ecgi in practice, the cell Id
+ *
+ */
+ virtual void InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi) = 0;
+
+ struct ErabSetupItem
+ {
+ uint16_t erabId;
+ Ipv4Address transportLayerAddress;
+ uint32_t enbTeid;
+ };
+
+ /**
+ *
+ *
+ * \param mmeUeS1Id in practice, we use the IMSI
+ * \param enbUeS1Id in practice, we use the RNTI
+ * \param ecgi in practice, the cell Id
+ *
+ */
+ virtual void InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabSetupItem> erabSetupList) = 0;
+
+
+ /**
+ * E-RABs Switched in Downlink Item IE, see 3GPP TS 36.413 9.1.5.8
+ *
+ */
+ struct ErabSwitchedInDownlinkItem
+ {
+ uint16_t erabId;
+ Ipv4Address transportLayerAddress;
+ uint32_t enbTeid;
+ };
+
+ /**
+ * PATH SWITCH REQUEST message, see 3GPP TS 36.413 9.1.5.8
+ *
+ */
+ virtual void PathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList) = 0;
+};
+
+
+
+/**
+ * \ingroup lte
+ *
+ * eNB side of the S1-AP Service Access Point (SAP), provides the eNB
+ * methods to be called when an S1-AP message is received by the eNB.
+ */
+class EpcS1apSapEnb : public EpcS1apSap
+{
+public:
+
+
+ struct ErabToBeSetupItem
+ {
+ uint16_t erabId;
+ EpsBearer erabLevelQosParameters;
+ Ipv4Address transportLayerAddress;
+ uint32_t sgwTeid;
+ };
+
+ /**
+ *
+ *
+ * \param mmeUeS1Id in practice, we use the IMSI
+ * \param enbUeS1Id in practice, we use the RNTI
+ * \param ecgi in practice, the cell Id
+ *
+ */
+ virtual void InitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabToBeSetupItem> erabToBeSetupList) = 0;
+
+
+ /**
+ * E-RABs Switched in Uplink Item IE, see 3GPP TS 36.413 9.1.5.9
+ *
+ */
+ struct ErabSwitchedInUplinkItem
+ {
+ uint16_t erabId;
+ Ipv4Address transportLayerAddress;
+ uint32_t enbTeid;
+ };
+
+ /**
+ * PATH SWITCH REQUEST ACKNOWLEDGE message, see 3GPP TS 36.413 9.1.5.9
+ *
+ */
+ virtual void PathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList) = 0;
+
+
+};
+
+
+
+
+
+
+/**
+ * Template for the implementation of the EpcS1apSapMme as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberEpcS1apSapMme : public EpcS1apSapMme
+{
+public:
+ MemberEpcS1apSapMme (C* owner);
+
+ // inherited from EpcS1apSapMme
+ virtual void InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi);
+ virtual void InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabSetupItem> erabSetupList);
+ virtual void PathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList);
+
+private:
+ MemberEpcS1apSapMme ();
+ C* m_owner;
+};
+
+template <class C>
+MemberEpcS1apSapMme<C>::MemberEpcS1apSapMme (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberEpcS1apSapMme<C>::MemberEpcS1apSapMme ()
+{
+}
+
+template <class C>
+void MemberEpcS1apSapMme<C>::InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi)
+{
+ m_owner->DoInitialUeMessage (mmeUeS1Id, enbUeS1Id, imsi, ecgi);
+}
+
+template <class C>
+void MemberEpcS1apSapMme<C>::InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabSetupItem> erabSetupList)
+{
+ m_owner->DoInitialContextSetupResponse (mmeUeS1Id, enbUeS1Id, erabSetupList);
+}
+
+template <class C>
+void MemberEpcS1apSapMme<C>::PathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
+{
+ m_owner->DoPathSwitchRequest (enbUeS1Id, mmeUeS1Id, cgi, erabToBeSwitchedInDownlinkList);
+}
+
+
+
+
+
+
+
+/**
+ * Template for the implementation of the EpcS1apSapEnb as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberEpcS1apSapEnb : public EpcS1apSapEnb
+{
+public:
+ MemberEpcS1apSapEnb (C* owner);
+
+ // inherited from EpcS1apSapEnb
+ virtual void InitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabToBeSetupItem> erabToBeSetupList);
+ virtual void PathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList);
+
+private:
+ MemberEpcS1apSapEnb ();
+ C* m_owner;
+};
+
+template <class C>
+MemberEpcS1apSapEnb<C>::MemberEpcS1apSapEnb (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberEpcS1apSapEnb<C>::MemberEpcS1apSapEnb ()
+{
+}
+
+template <class C>
+void MemberEpcS1apSapEnb<C>::InitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabToBeSetupItem> erabToBeSetupList)
+{
+ m_owner->DoInitialContextSetupRequest (mmeUeS1Id, enbUeS1Id, erabToBeSetupList);
+}
+
+template <class C>
+void MemberEpcS1apSapEnb<C>::PathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
+{
+ m_owner->DoPathSwitchRequestAcknowledge (enbUeS1Id, mmeUeS1Id, cgi, erabToBeSwitchedInUplinkList);
+}
+
+
+
+
+
+
+
+} //namespace ns3
+
+#endif /* EPC_S1AP_SAP_H */
+
--- a/src/lte/model/epc-sgw-pgw-application.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-sgw-pgw-application.cc Wed Nov 28 11:37:28 2012 +0100
@@ -72,6 +72,18 @@
m_enbAddr = enbAddr;
}
+Ipv4Address
+EpcSgwPgwApplication::UeInfo::GetUeAddr ()
+{
+ return m_ueAddr;
+}
+
+void
+EpcSgwPgwApplication::UeInfo::SetUeAddr (Ipv4Address ueAddr)
+{
+ m_ueAddr = ueAddr;
+}
+
/////////////////////////
// EpcSgwPgwApplication
/////////////////////////
@@ -98,10 +110,12 @@
: m_s1uSocket (s1uSocket),
m_tunDevice (tunDevice),
m_gtpuUdpPort (2152), // fixed by the standard
- m_teidCount (0)
+ m_teidCount (0),
+ m_s11SapMme (0)
{
NS_LOG_FUNCTION (this << tunDevice << s1uSocket);
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromS1uSocket, this));
+ m_s11SapSgw = new MemberEpcS11SapSgw<EpcSgwPgwApplication> (this);
}
@@ -122,17 +136,9 @@
NS_ABORT_IF (m_teidCount == 0xFFFFFFFF);
uint32_t teid = ++m_teidCount;
- std::map<Ipv4Address, UeInfo>::iterator it = m_ueInfoMap.find (ueAddr);
- if (it == m_ueInfoMap.end ())
- {
- // UE unknown, creating new entry
- std::pair<std::map<Ipv4Address, UeInfo>::iterator, bool> ret;
- ret = m_ueInfoMap.insert (std::pair <Ipv4Address, UeInfo> (ueAddr, UeInfo ()));
- it = ret.first;
- it->second.SetEnbAddr (enbAddr);
- }
-
- it->second.AddBearer (tft, teid);
+ std::map<Ipv4Address, Ptr<UeInfo> >::iterator it = m_ueInfoByAddrMap.find (ueAddr);
+ NS_ASSERT (it != m_ueInfoByAddrMap.end ());
+ it->second->AddBearer (tft, teid);
return teid;
}
@@ -149,15 +155,15 @@
NS_LOG_LOGIC ("packet addressed to UE " << ueAddr);
// find corresponding UeInfo address
- std::map<Ipv4Address, UeInfo>::iterator it = m_ueInfoMap.find (ueAddr);
- if (it == m_ueInfoMap.end ())
+ std::map<Ipv4Address, Ptr<UeInfo> >::iterator it = m_ueInfoByAddrMap.find (ueAddr);
+ if (it == m_ueInfoByAddrMap.end ())
{
NS_LOG_WARN ("unknown UE address " << ueAddr) ;
}
else
{
- Ipv4Address enbAddr = it->second.GetEnbAddr ();
- uint32_t teid = it->second.Classify (packet);
+ Ipv4Address enbAddr = it->second->GetEnbAddr ();
+ uint32_t teid = it->second->Classify (packet);
if (teid == 0)
{
NS_LOG_WARN ("no matching bearer for this packet");
@@ -214,4 +220,84 @@
m_s1uSocket->SendTo (packet, flags, InetSocketAddress(enbAddr, m_gtpuUdpPort));
}
+
+void
+EpcSgwPgwApplication::SetS11SapMme (EpcS11SapMme * s)
+{
+ m_s11SapMme = s;
+}
+
+EpcS11SapSgw*
+EpcSgwPgwApplication::GetS11SapSgw ()
+{
+ return m_s11SapSgw;
+}
+
+void
+EpcSgwPgwApplication::AddEnb (uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr)
+{
+ NS_LOG_FUNCTION (this << cellId << enbAddr << sgwAddr);
+ EnbInfo enbInfo;
+ enbInfo.enbAddr = enbAddr;
+ enbInfo.sgwAddr = sgwAddr;
+ m_enbInfoByCellId[cellId] = enbInfo;
+}
+
+void
+EpcSgwPgwApplication::AddUe (uint64_t imsi)
+{
+ NS_LOG_FUNCTION (this << imsi);
+ Ptr<UeInfo> ueInfo = Create<UeInfo> ();
+ m_ueInfoByImsiMap[imsi] = ueInfo;
+}
+
+void
+EpcSgwPgwApplication::SetUeAddress (uint64_t imsi, Ipv4Address ueAddr)
+{
+ NS_LOG_FUNCTION (this << imsi << ueAddr);
+ std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi);
+ NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);
+ m_ueInfoByAddrMap[ueAddr] = ueit->second;
+ ueit->second->SetUeAddr (ueAddr);
+}
+
+void
+EpcSgwPgwApplication::DoRecvCreateSessionRequest (uint64_t imsi, EpcS11Sap::Uli uli, std::list<EpcS11SapSgw::BearerContext> bearersToBeSetup)
+{
+ NS_LOG_FUNCTION (this << imsi);
+ std::map<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi);
+ NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);
+ Ipv4Address ueAddr = ueit->second->GetUeAddr ();
+ uint16_t cellId = uli.gci;
+ std::map<uint16_t, EnbInfo>::iterator enbit = m_enbInfoByCellId.find (cellId);
+ NS_ASSERT_MSG (enbit != m_enbInfoByCellId.end (), "unknown CellId " << cellId);
+ Ipv4Address enbAddr = enbit->second.enbAddr;
+ ueit->second->SetEnbAddr (enbAddr);
+
+ // bearer context info to be fed back to the MME in the response
+ std::list<EpcS11SapMme::BearerContext> bearersContextList;
+
+ for (std::list<EpcS11SapSgw::BearerContext>::iterator bit = bearersToBeSetup.begin ();
+ bit != bearersToBeSetup.end ();
+ ++bit)
+ {
+ uint32_t teid = ActivateS1Bearer (ueAddr, enbAddr, bit->tft);
+ EpcS11SapMme::BearerContext bearerContext;
+ bearerContext.sgwFteid.teid = teid;
+ bearerContext.sgwFteid.address = enbit->second.sgwAddr;
+ bearerContext.epsBearerId = bit->epsBearerId;
+ bearerContext.bearerLevelQos = bit->bearerLevelQos;
+ bearerContext.tft = bit->tft;
+ bearersContextList.push_back (bearerContext);
+ }
+ m_s11SapMme->RecvCreateSessionResponse (imsi, bearersContextList);
+
+}
+
+void
+EpcSgwPgwApplication::DoModifyBearerRequest (uint64_t mei, EpcS11Sap::Uli uli, std::list<EpcS11SapSgw::BearerContext> bearersToBeSetup)
+{
+ NS_FATAL_ERROR ("not implemented");
+}
+
}; // namespace ns3
--- a/src/lte/model/epc-sgw-pgw-application.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-sgw-pgw-application.h Wed Nov 28 11:37:28 2012 +0100
@@ -34,6 +34,8 @@
#include <ns3/epc-tft-classifier.h>
#include <ns3/lte-common.h>
#include <ns3/application.h>
+#include <ns3/epc-s1ap-sap.h>
+#include <ns3/epc-s11-sap.h>
#include <map>
namespace ns3 {
@@ -45,6 +47,7 @@
*/
class EpcSgwPgwApplication : public Application
{
+ friend class MemberEpcS11SapSgw<EpcSgwPgwApplication>;
public:
@@ -125,14 +128,53 @@
void SendToS1uSocket (Ptr<Packet> packet, Ipv4Address enbS1uAddress, uint32_t teid);
+ /**
+ * Set the MME side of the S11 SAP
+ *
+ * \param s the MME side of the S11 SAP
+ */
+ void SetS11SapMme (EpcS11SapMme * s);
+
+ /**
+ *
+ * \return the SGW side of the S11 SAP
+ */
+ EpcS11SapSgw* GetS11SapSgw ();
+
+
+ /**
+ * Let the SGW be aware of a new eNB
+ *
+ * \param cellId the cell identifier
+ * \param enbAdd the address of the eNB
+ */
+ void AddEnb (uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr);
+
+ /**
+ * Let the SGW be aware of a new UE
+ *
+ * \param imsi the unique identifier of the UE
+ */
+ void AddUe (uint64_t imsi);
+
+ /**
+ * set the address of a previously added UE
+ *
+ * \param imsi the unique identifier of the UE
+ * \param ueAddr the IPv4 address of the UE
+ */
+ void SetUeAddress (uint64_t imsi, Ipv4Address ueAddr);
private:
+ // S11 SAP SGW methods
+ void DoRecvCreateSessionRequest (uint64_t imsi, EpcS11Sap::Uli uli, std::list<EpcS11SapSgw::BearerContext> bearersToBeSetup);
+ void DoModifyBearerRequest (uint64_t mei, EpcS11Sap::Uli uli, std::list<EpcS11SapSgw::BearerContext> bearersToBeSetup);
/**
* store info for each UE connected to this SGW
*/
- class UeInfo
+ class UeInfo : public SimpleRefCount<UeInfo>
{
public:
UeInfo ();
@@ -167,10 +209,23 @@
*/
void SetEnbAddr (Ipv4Address addr);
+ /**
+ * \return the address of the UE
+ */
+ Ipv4Address GetUeAddr ();
+
+ /**
+ * set the address of the UE
+ *
+ * \param addr the address of the UE
+ */
+ void SetUeAddr (Ipv4Address addr);
+
private:
EpcTftClassifier m_tftClassifier;
Ipv4Address m_enbAddr;
+ Ipv4Address m_ueAddr;
};
@@ -188,7 +243,12 @@
/**
* Map telling for each UE address the corresponding UE info
*/
- std::map<Ipv4Address, UeInfo> m_ueInfoMap;
+ std::map<Ipv4Address, Ptr<UeInfo> > m_ueInfoByAddrMap;
+
+ /**
+ * Map telling for each IMSI the corresponding UE info
+ */
+ std::map<uint64_t, Ptr<UeInfo> > m_ueInfoByImsiMap;
/**
* UDP port to be used for GTP
@@ -197,6 +257,25 @@
uint32_t m_teidCount;
+ /**
+ * MME side of the S11 SAP
+ *
+ */
+ EpcS11SapMme* m_s11SapMme;
+
+ /**
+ * SGW side of the S11 SAP
+ *
+ */
+ EpcS11SapSgw* m_s11SapSgw;
+
+ struct EnbInfo
+ {
+ Ipv4Address enbAddr;
+ Ipv4Address sgwAddr;
+ };
+
+ std::map<uint16_t, EnbInfo> m_enbInfoByCellId;
};
} //namespace ns3
--- a/src/lte/model/epc-ue-nas.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-ue-nas.cc Wed Nov 28 11:37:28 2012 +0100
@@ -73,8 +73,7 @@
EpcUeNas::DoDispose ()
{
NS_LOG_FUNCTION (this);
- delete m_asSapUser;
- m_epcHelper = 0;
+ delete m_asSapUser;
}
TypeId
@@ -90,13 +89,6 @@
return tid;
}
-
-void
-EpcUeNas::SetEpcHelper (Ptr<EpcHelper> epcHelper)
-{
- m_epcHelper = epcHelper;
-}
-
void
EpcUeNas::SetDevice (Ptr<NetDevice> dev)
{
@@ -128,16 +120,13 @@
}
void
-EpcUeNas::Connect (Ptr<NetDevice> enbDevice)
+EpcUeNas::Connect (uint16_t cellId, uint16_t earfcn)
{
NS_LOG_FUNCTION (this);
- m_enbDevice = enbDevice;
-
// since RRC Idle Mode cell selection is not supported yet, we
// force the UE RRC to be camped on a specific eNB
- Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
- m_asSapProvider->ForceCampedOnEnb (enbLteDevice, enbLteDevice->GetCellId ());
+ m_asSapProvider->ForceCampedOnEnb (cellId, earfcn);
// tell RRC to go into connected mode
m_asSapProvider->Connect ();
@@ -160,7 +149,7 @@
switch (m_state)
{
case ACTIVE:
- DoActivateEpsBearer (bearer, tft);
+ NS_FATAL_ERROR ("the necessary NAS signaling to activate a bearer after the initial context has already been setup is not implemented");
break;
default:
@@ -207,13 +196,8 @@
EpcUeNas::DoNotifyConnectionSuccessful ()
{
NS_LOG_FUNCTION (this);
- if (m_epcHelper)
- {
- m_epcHelper->AttachUe (m_device, m_imsi, m_enbDevice);
- // also activate default EPS bearer
- DoActivateEpsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
- SwitchToState (ACTIVE);
- }
+
+ SwitchToState (ACTIVE); // will eventually activate dedicated bearers
}
void
@@ -241,7 +225,6 @@
NS_LOG_FUNCTION (this);
NS_ASSERT_MSG (m_bidCounter < 11, "cannot have more than 11 EPS bearers");
uint8_t bid = ++m_bidCounter;
- m_epcHelper->ActivateEpsBearer (m_device, m_imsi, tft, bearer);
m_tftClassifier.Add (tft, bid);
}
--- a/src/lte/model/epc-ue-nas.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/epc-ue-nas.h Wed Nov 28 11:37:28 2012 +0100
@@ -50,13 +50,6 @@
virtual void DoDispose (void);
static TypeId GetTypeId (void);
- /**
- * set the EpcHelper with which the NAS will interact as if it were the MME
- *
- * \param epcHelper
- */
- void SetEpcHelper (Ptr<EpcHelper> epcHelper);
-
/**
*
@@ -94,12 +87,13 @@
/**
* instruct the NAS to go to ACTIVE state, i.e., EMM Registered + ECM Connected
- *
+ * Since RRC Idle Mode cell selection is not supported yet, we
+ * force the UE RRC to be camped on a specific eNB.
*
- * \param enbDevice the eNB through which to connect. This parameter
- * might be removed in future versions.
+ * \param cellId the id of the eNB to camp on
+ * \param earfcn the DL frequency of the eNB
*/
- void Connect (Ptr<NetDevice> enbDevice);
+ void Connect (uint16_t cellId, uint16_t earfcn);
/**
* instruct the NAS to disconnect
@@ -158,11 +152,8 @@
TracedCallback<State, State> m_stateTransitionCallback;
- Ptr<EpcHelper> m_epcHelper;
Ptr<NetDevice> m_device;
- Ptr<NetDevice> m_enbDevice; // might go away in future versions
-
uint64_t m_imsi;
LteAsSapProvider* m_asSapProvider;
--- a/src/lte/model/lte-as-sap.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/lte-as-sap.h Wed Nov 28 11:37:28 2012 +0100
@@ -50,7 +50,7 @@
* future versions)
* \param cellId the Cell ID identifying the eNB
*/
- virtual void ForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId) = 0;
+ virtual void ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn) = 0;
/**
* Tell the RRC to go into Connected Mode
@@ -133,7 +133,7 @@
// inherited from LteAsSapProvider
virtual void Connect (void);
- virtual void ForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
+ virtual void ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn);
virtual void SendData (Ptr<Packet> packet, uint8_t bid);
virtual void Disconnect ();
@@ -155,9 +155,9 @@
template <class C>
void
-MemberLteAsSapProvider<C>::ForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId)
+MemberLteAsSapProvider<C>::ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn)
{
- m_owner->DoForceCampedOnEnb (enbDevice, cellId);
+ m_owner->DoForceCampedOnEnb (cellId, earfcn);
}
--- a/src/lte/model/lte-ue-net-device.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/lte-ue-net-device.cc Wed Nov 28 11:37:28 2012 +0100
@@ -188,12 +188,6 @@
}
void
-LteUeNetDevice::ActivateDedicatedEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft)
-{
- m_nas->ActivateEpsBearer (bearer, tft);
-}
-
-void
LteUeNetDevice::DoStart (void)
{
NS_LOG_FUNCTION (this);
--- a/src/lte/model/lte-ue-net-device.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/lte-ue-net-device.h Wed Nov 28 11:37:28 2012 +0100
@@ -97,13 +97,6 @@
*/
Ptr<LteEnbNetDevice> GetTargetEnb (void);
- /**
- * Activate a dedicated EPS bearer
- *
- * \param bearer the bearer paramaters
- * \param tft the TFT identifying the traffic that will go over the bearer
- */
- void ActivateDedicatedEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft);
protected:
// inherited from Object
--- a/src/lte/model/lte-ue-rrc.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/lte-ue-rrc.cc Wed Nov 28 11:37:28 2012 +0100
@@ -445,12 +445,12 @@
void
-LteUeRrc::DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbLteDevice, uint16_t cellId)
+LteUeRrc::DoForceCampedOnEnb (uint16_t cellId, uint16_t earfcn)
{
- NS_LOG_FUNCTION (this << cellId);
+ NS_LOG_FUNCTION (this << cellId << earfcn);
m_cellId = cellId;
- m_dlEarfcn = enbLteDevice->GetDlEarfcn ();
+ m_dlEarfcn = earfcn;
m_cphySapProvider->SyncronizeWithEnb (m_cellId, m_dlEarfcn);
SwitchToState (IDLE_WAIT_SYSTEM_INFO);
}
--- a/src/lte/model/lte-ue-rrc.h Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/model/lte-ue-rrc.h Wed Nov 28 11:37:28 2012 +0100
@@ -230,7 +230,7 @@
void DoNotifyRandomAccessFailed ();
// LTE AS SAP methods
- void DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
+ void DoForceCampedOnEnb (uint16_t cellId, uint16_t earfcn);
void DoConnect ();
void DoSendData (Ptr<Packet> packet, uint8_t bid);
void DoDisconnect ();
--- a/src/lte/test/epc-test-s1u-downlink.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/test/epc-test-s1u-downlink.cc Wed Nov 28 11:37:28 2012 +0100
@@ -131,6 +131,7 @@
NodeContainer enbs;
+ uint16_t cellIdCounter = 0;
for (std::vector<EnbDlTestData>::iterator enbit = m_enbDlTestData.begin ();
enbit < m_enbDlTestData.end ();
@@ -143,6 +144,8 @@
// 1) a CSMA network to simulate the cell
// 2) a raw socket opened on the CSMA device to simulate the LTE socket
+ uint16_t cellId = ++cellIdCounter;
+
NodeContainer ues;
ues.Create (enbit->ues.size ());
@@ -157,7 +160,7 @@
Ptr<NetDevice> enbDevice = cellDevices.Get (cellDevices.GetN () - 1);
// Note that the EpcEnbApplication won't care of the actual NetDevice type
- epcHelper->AddEnb (enb, enbDevice);
+ epcHelper->AddEnb (enb, enbDevice, cellId);
// Plug test RRC entity
Ptr<EpcEnbApplication> enbApp = enb->GetApplication (0)->GetObject<EpcEnbApplication> ();
@@ -201,9 +204,9 @@
enbit->ues[u].clientApp = apps.Get (0);
uint64_t imsi = u+1;
- epcHelper->AttachUe (ueLteDevice, imsi, enbDevice);
+ epcHelper->AddUe (ueLteDevice, imsi);
+ epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
enbApp->GetS1SapProvider ()->InitialUeMessage (imsi, (uint16_t) imsi);
- epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
}
}
--- a/src/lte/test/epc-test-s1u-uplink.cc Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/test/epc-test-s1u-uplink.cc Wed Nov 28 11:37:28 2012 +0100
@@ -328,18 +328,21 @@
uint16_t udpSinkPort = 1234;
NodeContainer enbs;
+ uint16_t cellIdCounter = 0;
for (std::vector<EnbUlTestData>::iterator enbit = m_enbUlTestData.begin ();
enbit < m_enbUlTestData.end ();
++enbit)
{
Ptr<Node> enb = CreateObject<Node> ();
- enbs.Add (enb);
+ enbs.Add (enb);
// we test EPC without LTE, hence we use:
// 1) a CSMA network to simulate the cell
// 2) a raw socket opened on the CSMA device to simulate the LTE socket
+ uint16_t cellId = ++cellIdCounter;
+
NodeContainer ues;
ues.Create (enbit->ues.size ());
@@ -354,7 +357,7 @@
Ptr<NetDevice> enbDevice = cellDevices.Get (cellDevices.GetN () - 1);
// Note that the EpcEnbApplication won't care of the actual NetDevice type
- epcHelper->AddEnb (enb, enbDevice);
+ epcHelper->AddEnb (enb, enbDevice, cellId);
// Plug test RRC entity
Ptr<EpcEnbApplication> enbApp = enb->GetApplication (0)->GetObject<EpcEnbApplication> ();
@@ -424,9 +427,9 @@
enbit->ues[u].clientApp = client;
uint64_t imsi = u+1;
- epcHelper->AttachUe (ueLteDevice, imsi, enbDevice);
+ epcHelper->AddUe (ueLteDevice, imsi);
+ epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
enbApp->GetS1SapProvider ()->InitialUeMessage (imsi, (uint16_t) imsi);
- epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
// need this since all sinks are installed in the same node
++udpSinkPort;
--- a/src/lte/wscript Mon Nov 26 16:25:28 2012 +0100
+++ b/src/lte/wscript Wed Nov 28 11:37:28 2012 +0100
@@ -76,9 +76,12 @@
'model/lte-mi-error-model.cc',
'model/lte-vendor-specific-parameters.cc',
'model/epc-enb-s1-sap.cc',
+ 'model/epc-s1ap-sap.cc',
+ 'model/epc-s11-sap.cc',
'model/lte-as-sap.cc',
'model/epc-ue-nas.cc',
'model/lte-harq-phy.cc',
+ 'model/epc-mme.cc',
]
module_test = bld.create_ns3_module_test_library('lte')
@@ -191,9 +194,12 @@
'test/lte-test-ue-phy.h',
'test/lte-test-sinr-chunk-processor.h',
'model/epc-enb-s1-sap.h',
+ 'model/epc-s1ap-sap.h',
+ 'model/epc-s11-sap.h',
'model/lte-as-sap.h',
'model/epc-ue-nas.h',
'model/lte-harq-phy.h',
+ 'model/epc-mme.h',
]
if (bld.env['ENABLE_EXAMPLES']):