Commit 52803737 authored by aligungr's avatar aligungr

T3580 handling

parent 3b54ec48
...@@ -149,7 +149,7 @@ void GnbMrTask::onUeConnected(int ue, const std::string &name) ...@@ -149,7 +149,7 @@ void GnbMrTask::onUeConnected(int ue, const std::string &name)
m_ueMap[ue].ueId = ue; m_ueMap[ue].ueId = ue;
m_ueMap[ue].name = name; m_ueMap[ue].name = name;
m_logger->info("New UE connected to gNB. Total number of UEs is now: %d", m_ueMap.size()); m_logger->info("New UE connected to gNB. Total number of UEs [%d]", m_ueMap.size());
} }
void GnbMrTask::onUeReleased(int ue, rls::ECause cause) void GnbMrTask::onUeReleased(int ue, rls::ECause cause)
...@@ -164,7 +164,7 @@ void GnbMrTask::onUeReleased(int ue, rls::ECause cause) ...@@ -164,7 +164,7 @@ void GnbMrTask::onUeReleased(int ue, rls::ECause cause)
} }
m_ueMap.erase(ue); m_ueMap.erase(ue);
m_logger->info("A UE disconnected from gNB. Total number of UEs is now: %d", m_ueMap.size()); m_logger->info("A UE disconnected from gNB. Total number of UEs [%d]", m_ueMap.size());
} }
void GnbMrTask::receiveUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload) void GnbMrTask::receiveUplinkPayload(int ue, rls::EPayloadType type, OctetString &&payload)
......
...@@ -15,41 +15,41 @@ namespace nas ...@@ -15,41 +15,41 @@ namespace nas
{ {
NasTimer::NasTimer(int timerCode, bool isMmTimer, int defaultInterval) NasTimer::NasTimer(int timerCode, bool isMmTimer, int defaultInterval)
: timerCode(timerCode), mmTimer(isMmTimer), interval(defaultInterval), startMillis(0), running(false), : m_code(timerCode), m_isMm(isMmTimer), m_interval(defaultInterval), m_startMillis(0), m_isRunning(false),
expiryCount(0), _lastDebugPrintMs(0) m_expiryCount(0), m_lastDebugPrintMs(0)
{ {
} }
bool NasTimer::isRunning() const bool NasTimer::isRunning() const
{ {
return running; return m_isRunning;
} }
int NasTimer::getCode() const int NasTimer::getCode() const
{ {
return timerCode; return m_code;
} }
bool NasTimer::isMmTimer() const bool NasTimer::isMmTimer() const
{ {
return mmTimer; return m_isMm;
} }
void NasTimer::start(bool clearExpiryCount) void NasTimer::start(bool clearExpiryCount)
{ {
if (clearExpiryCount) if (clearExpiryCount)
resetExpiryCount(); resetExpiryCount();
startMillis = utils::CurrentTimeMillis(); m_startMillis = utils::CurrentTimeMillis();
running = true; m_isRunning = true;
} }
void NasTimer::start(const nas::IEGprsTimer2 &v, bool clearExpiryCount) void NasTimer::start(const nas::IEGprsTimer2 &v, bool clearExpiryCount)
{ {
if (clearExpiryCount) if (clearExpiryCount)
resetExpiryCount(); resetExpiryCount();
interval = v.value; m_interval = v.value;
startMillis = utils::CurrentTimeMillis(); m_startMillis = utils::CurrentTimeMillis();
running = true; m_isRunning = true;
} }
void NasTimer::start(const nas::IEGprsTimer3 &v, bool clearExpiryCount) void NasTimer::start(const nas::IEGprsTimer3 &v, bool clearExpiryCount)
...@@ -75,9 +75,9 @@ void NasTimer::start(const nas::IEGprsTimer3 &v, bool clearExpiryCount) ...@@ -75,9 +75,9 @@ void NasTimer::start(const nas::IEGprsTimer3 &v, bool clearExpiryCount)
else if (v.unit == nas::EGprsTimerValueUnit3::MULTIPLES_OF_320HOUR) else if (v.unit == nas::EGprsTimerValueUnit3::MULTIPLES_OF_320HOUR)
secs = val * 60 * 60 * 320; secs = val * 60 * 60 * 320;
interval = secs; m_interval = secs;
startMillis = utils::CurrentTimeMillis(); m_startMillis = utils::CurrentTimeMillis();
running = true; m_isRunning = true;
} }
void NasTimer::stop(bool clearExpiryCount) void NasTimer::stop(bool clearExpiryCount)
...@@ -85,31 +85,31 @@ void NasTimer::stop(bool clearExpiryCount) ...@@ -85,31 +85,31 @@ void NasTimer::stop(bool clearExpiryCount)
if (clearExpiryCount) if (clearExpiryCount)
resetExpiryCount(); resetExpiryCount();
if (running) if (m_isRunning)
{ {
startMillis = utils::CurrentTimeMillis(); m_startMillis = utils::CurrentTimeMillis();
running = false; m_isRunning = false;
} }
} }
bool NasTimer::performTick() bool NasTimer::performTick()
{ {
if (running) if (m_isRunning)
{ {
long currentMs = utils::CurrentTimeMillis(); long currentMs = utils::CurrentTimeMillis();
long deltaSec = (currentMs - startMillis) / 1000LL; long deltaSec = (currentMs - m_startMillis) / 1000LL;
long remainingSec = interval - deltaSec; long remainingSec = m_interval - deltaSec;
if (currentMs - _lastDebugPrintMs > 10LL * 1000LL) if (currentMs - m_lastDebugPrintMs > 10LL * 1000LL)
{ {
_lastDebugPrintMs = currentMs; m_lastDebugPrintMs = currentMs;
// Log.debug(Tag.TIMER, "NAS Timer %s int:%ss rem:%ss", timerCode, interval, remainingSec); // Log.debug(Tag.TIMER, "NAS Timer %s int:%ss rem:%ss", timerCode, interval, remainingSec);
} }
if (remainingSec <= 0LL) if (remainingSec <= 0LL)
{ {
stop(false); stop(false);
expiryCount++; m_expiryCount++;
return true; return true;
} }
} }
...@@ -118,26 +118,26 @@ bool NasTimer::performTick() ...@@ -118,26 +118,26 @@ bool NasTimer::performTick()
int NasTimer::getInterval() const int NasTimer::getInterval() const
{ {
return interval; return m_interval;
} }
int NasTimer::getRemaining() const int NasTimer::getRemaining() const
{ {
if (!running) if (!m_isRunning)
return 0; return 0;
int elapsed = static_cast<int>((utils::CurrentTimeMillis() - startMillis) / 1000LL); int elapsed = static_cast<int>((utils::CurrentTimeMillis() - m_startMillis) / 1000LL);
return std::max(interval - elapsed, 0); return std::max(m_interval - elapsed, 0);
} }
void NasTimer::resetExpiryCount() void NasTimer::resetExpiryCount()
{ {
expiryCount = 0; m_expiryCount = 0;
} }
int NasTimer::getExpiryCount() const int NasTimer::getExpiryCount() const
{ {
return expiryCount; return m_expiryCount;
} }
Json ToJson(const NasTimer &v) Json ToJson(const NasTimer &v)
......
...@@ -18,15 +18,15 @@ namespace nas ...@@ -18,15 +18,15 @@ namespace nas
class NasTimer class NasTimer
{ {
private: private:
const int timerCode; const int m_code;
const bool mmTimer; const bool m_isMm;
int interval; int m_interval;
long startMillis; long m_startMillis;
bool running; bool m_isRunning;
int expiryCount; int m_expiryCount;
long _lastDebugPrintMs; long m_lastDebugPrintMs;
public: public:
NasTimer(int timerCode, bool isMmTimer, int defaultInterval); NasTimer(int timerCode, bool isMmTimer, int defaultInterval);
......
...@@ -74,9 +74,7 @@ void NasTask::onLoop() ...@@ -74,9 +74,7 @@ void NasTask::onLoop()
if (w->timer->isMmTimer()) if (w->timer->isMmTimer())
mm->handleNasEvent(*w); mm->handleNasEvent(*w);
else else
{ sm->handleNasEvent(*w);
// TODO, handle SM timer
}
break; break;
case NwUeNasToNas::ESTABLISH_INITIAL_SESSIONS: case NwUeNasToNas::ESTABLISH_INITIAL_SESSIONS:
sm->establishInitialSessions(); sm->establishInitialSessions();
...@@ -147,18 +145,12 @@ void NasTask::performTick() ...@@ -147,18 +145,12 @@ void NasTask::performTick()
sendExpireMsg(&timers.t3525); sendExpireMsg(&timers.t3525);
if (timers.t3540.performTick()) if (timers.t3540.performTick())
sendExpireMsg(&timers.t3540); sendExpireMsg(&timers.t3540);
if (timers.t3580.performTick())
sendExpireMsg(&timers.t3580);
if (timers.t3581.performTick())
sendExpireMsg(&timers.t3581);
if (timers.t3582.performTick())
sendExpireMsg(&timers.t3582);
if (timers.t3583.performTick())
sendExpireMsg(&timers.t3583);
if (timers.t3584.performTick()) if (timers.t3584.performTick())
sendExpireMsg(&timers.t3584); sendExpireMsg(&timers.t3584);
if (timers.t3585.performTick()) if (timers.t3585.performTick())
sendExpireMsg(&timers.t3585); sendExpireMsg(&timers.t3585);
sm->onTimerTick();
} }
} // namespace nr::ue } // namespace nr::ue
\ No newline at end of file
...@@ -48,7 +48,7 @@ int NasSm::allocateProcedureTransactionId() ...@@ -48,7 +48,7 @@ int NasSm::allocateProcedureTransactionId()
int id = -1; int id = -1;
for (int i = ProcedureTransaction::MIN_ID; i <= ProcedureTransaction::MAX_ID; i++) for (int i = ProcedureTransaction::MIN_ID; i <= ProcedureTransaction::MAX_ID; i++)
{ {
if (!arr[i].isUsed) if (arr[i].state == EPtState::INACTIVE)
{ {
id = i; id = i;
break; break;
......
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "sm.hpp"
#include <algorithm>
#include <nas/proto_conf.hpp>
#include <nas/utils.hpp>
#include <ue/app/task.hpp>
#include <ue/mm/mm.hpp>
namespace nr::ue
{
void NasSm::handleNasEvent(const NwUeNasToNas &msg)
{
switch (msg.present)
{
case NwUeNasToNas::NAS_TIMER_EXPIRE:
onTimerExpire(*msg.timer);
break;
default:
break;
}
}
void NasSm::onTimerTick()
{
int pti = 0;
for (auto &pt : m_procedureTransactions)
{
if (pt.timer && pt.timer->performTick())
onTransactionTimerExpire(pti);
pti++;
}
}
} // namespace nr::ue
...@@ -79,7 +79,7 @@ void NasSm::sendEstablishmentRequest(const SessionConfig &config) ...@@ -79,7 +79,7 @@ void NasSm::sendEstablishmentRequest(const SessionConfig &config)
} }
/* Set relevant fields of the PS description */ /* Set relevant fields of the PS description */
auto ps = m_pduSessions[psi]; auto &ps = m_pduSessions[psi];
ps->psState = EPsState::ACTIVE_PENDING; ps->psState = EPsState::ACTIVE_PENDING;
ps->sessionType = config.type; ps->sessionType = config.type;
ps->apn = config.apn; ps->apn = config.apn;
...@@ -103,22 +103,26 @@ void NasSm::sendEstablishmentRequest(const SessionConfig &config) ...@@ -103,22 +103,26 @@ void NasSm::sendEstablishmentRequest(const SessionConfig &config)
iePco.options = opt.encode(); iePco.options = opt.encode();
/* Prepare the establishment request message */ /* Prepare the establishment request message */
nas::PduSessionEstablishmentRequest req{}; auto req = std::make_unique<nas::PduSessionEstablishmentRequest>();
req.pti = pti; req->pti = pti;
req.pduSessionId = static_cast<nas::EPduSessionIdentity>(psi); req->pduSessionId = static_cast<nas::EPduSessionIdentity>(psi);
req.integrityProtectionMaximumDataRate = MakeIntegrityMaxRate(m_base->config->integrityMaxRate); req->integrityProtectionMaximumDataRate = MakeIntegrityMaxRate(m_base->config->integrityMaxRate);
req.pduSessionType = nas::IEPduSessionType{}; req->pduSessionType = nas::IEPduSessionType{};
req.pduSessionType->pduSessionType = nas::EPduSessionType::IPV4; req->pduSessionType->pduSessionType = nas::EPduSessionType::IPV4;
req.sscMode = nas::IESscMode{}; req->sscMode = nas::IESscMode{};
req.sscMode->sscMode = nas::ESscMode::SSC_MODE_1; req->sscMode->sscMode = nas::ESscMode::SSC_MODE_1;
req.extendedProtocolConfigurationOptions = std::move(iePco); req->extendedProtocolConfigurationOptions = std::move(iePco);
req.smCapability = MakeSmCapability(); req->smCapability = MakeSmCapability();
/* Start T3580 */ /* Set relevant fields of the PT, and start T3580 */
m_timers->t3580.start(); auto &pt = m_procedureTransactions[pti];
pt.state = EPtState::PENDING;
pt.timer = newTransactionTimer(3580);
pt.message = std::move(req);
pt.psi = psi;
/* Send SM message */ /* Send SM message */
sendSmMessage(psi, req); sendSmMessage(psi, *pt.message);
} }
void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &msg) void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &msg)
...@@ -129,8 +133,6 @@ void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishm ...@@ -129,8 +133,6 @@ void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishm
nas::utils::EnumToString(msg.smCause->value)); nas::utils::EnumToString(msg.smCause->value));
} }
m_timers->t3580.stop();
freeProcedureTransactionId(msg.pti); freeProcedureTransactionId(msg.pti);
auto pduSession = m_pduSessions[static_cast<int>(msg.pduSessionId)]; auto pduSession = m_pduSessions[static_cast<int>(msg.pduSessionId)];
...@@ -169,4 +171,14 @@ void NasSm::receivePduSessionEstablishmentReject(const nas::PduSessionEstablishm ...@@ -169,4 +171,14 @@ void NasSm::receivePduSessionEstablishmentReject(const nas::PduSessionEstablishm
// TODO // TODO
} }
void NasSm::abortEstablishmentRequest(int pti)
{
int psi = m_procedureTransactions[pti].psi;
m_logger->debug("PDU Session Establishment Procedure aborted for PTI[%d], PSI[%d]", pti, psi);
freeProcedureTransactionId(pti);
freePduSessionId(psi);
}
} // namespace nr::ue } // namespace nr::ue
\ No newline at end of file
...@@ -28,7 +28,7 @@ class NasSm ...@@ -28,7 +28,7 @@ class NasSm
std::unique_ptr<Logger> m_logger; std::unique_ptr<Logger> m_logger;
NasMm *m_mm; NasMm *m_mm;
std::array<PduSession*, 16> m_pduSessions{}; std::array<PduSession *, 16> m_pduSessions{};
std::array<ProcedureTransaction, 255> m_procedureTransactions{}; std::array<ProcedureTransaction, 255> m_procedureTransactions{};
friend class UeCmdHandler; friend class UeCmdHandler;
...@@ -67,6 +67,17 @@ class NasSm ...@@ -67,6 +67,17 @@ class NasSm
void sendEstablishmentRequest(const SessionConfig &config); void sendEstablishmentRequest(const SessionConfig &config);
void receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &msg); void receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &msg);
void receivePduSessionEstablishmentReject(const nas::PduSessionEstablishmentReject &msg); void receivePduSessionEstablishmentReject(const nas::PduSessionEstablishmentReject &msg);
void abortEstablishmentRequest(int pti);
/* Timer */
std::unique_ptr<nas::NasTimer> newTransactionTimer(int code);
void onTimerExpire(nas::NasTimer &timer);
void onTransactionTimerExpire(int pti);
public:
/* Interface */
void handleNasEvent(const NwUeNasToNas &msg); // used by NAS
void onTimerTick(); // used by NAS
}; };
} // namespace nr::ue } // namespace nr::ue
\ No newline at end of file
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include "sm.hpp"
#include <algorithm>
#include <nas/proto_conf.hpp>
#include <nas/utils.hpp>
#include <ue/app/task.hpp>
#include <ue/mm/mm.hpp>
namespace nr::ue
{
std::unique_ptr<nas::NasTimer> NasSm::newTransactionTimer(int code)
{
std::unique_ptr<nas::NasTimer> timer;
switch (code)
{
case 3580:
timer = std::make_unique<nas::NasTimer>(3580, false, 16);
break;
case 3581:
timer = std::make_unique<nas::NasTimer>(3581, false, 16);
break;
case 3582:
timer = std::make_unique<nas::NasTimer>(3582, false, 16);
break;
default:
m_logger->err("Bad SM transaction timer code");
return nullptr;
}
timer->start();
return timer;
}
void NasSm::onTimerExpire(nas::NasTimer &timer)
{
}
void NasSm::onTransactionTimerExpire(int pti)
{
auto &pt = m_procedureTransactions[pti];
if (pt.state == EPtState::INACTIVE)
return;
switch (pt.timer->getCode())
{
case 3580: {
if (pt.timer->getExpiryCount() < 5)
{
m_logger->warn("Retransmitting PDU Session Establishment Request due to T3580 expiry");
sendSmMessage(pt.psi, *pt.message);
pt.timer->start(false);
}
else
{
m_logger->err("PDU Session Establishment Procedure failure, no response from the network after 5 attempts");
abortEstablishmentRequest(pti);
}
break;
}
}
}
} // namespace nr::ue
\ No newline at end of file
...@@ -17,7 +17,6 @@ UeTimers::UeTimers() ...@@ -17,7 +17,6 @@ UeTimers::UeTimers()
t3445(3445, true, 12 * 60 * 60), t3502(3502, true, 12 * 60), t3510(3510, true, 15), t3511(3511, true, 10), t3445(3445, true, 12 * 60 * 60), t3502(3502, true, 12 * 60), t3510(3510, true, 15), t3511(3511, true, 10),
t3512(3512, true, 54 * 60), t3516(3516, true, 30), t3517(3517, true, 15), t3519(3519, true, 60), t3512(3512, true, 54 * 60), t3516(3516, true, 30), t3517(3517, true, 15), t3519(3519, true, 60),
t3520(3520, true, 15), t3521(3521, true, 15), t3525(3525, true, 60), t3540(3540, true, 10), t3520(3520, true, 15), t3521(3521, true, 15), t3525(3525, true, 60), t3540(3540, true, 10),
t3580(3580, false, 16), t3581(3581, false, 16), t3582(3582, false, 16), t3583(3583, false, 60),
t3584(3584, false, INT32_MAX), t3585(3585, false, INT32_MAX) t3584(3584, false, INT32_MAX), t3585(3585, false, INT32_MAX)
{ {
} }
...@@ -133,11 +132,22 @@ Json ToJson(const UeConfig &v) ...@@ -133,11 +132,22 @@ Json ToJson(const UeConfig &v)
Json ToJson(const UeTimers &v) Json ToJson(const UeTimers &v)
{ {
return Json::Obj({ return Json::Obj({
{"T3346", ToJson(v.t3346)}, {"T3396", ToJson(v.t3396)}, {"T3444", ToJson(v.t3444)}, {"T3445", ToJson(v.t3445)}, {"T3346", ToJson(v.t3346)},
{"T3502", ToJson(v.t3502)}, {"T3510", ToJson(v.t3510)}, {"T3511", ToJson(v.t3511)}, {"T3512", ToJson(v.t3512)}, {"T3396", ToJson(v.t3396)},
{"T3516", ToJson(v.t3516)}, {"T3517", ToJson(v.t3517)}, {"T3519", ToJson(v.t3519)}, {"T3520", ToJson(v.t3520)}, {"T3444", ToJson(v.t3444)},
{"T3521", ToJson(v.t3521)}, {"T3525", ToJson(v.t3525)}, {"T3540", ToJson(v.t3540)}, {"T3580", ToJson(v.t3580)}, {"T3445", ToJson(v.t3445)},
{"T3581", ToJson(v.t3581)}, {"T3582", ToJson(v.t3582)}, {"T3583", ToJson(v.t3583)}, {"T3584", ToJson(v.t3584)}, {"T3502", ToJson(v.t3502)},
{"T3510", ToJson(v.t3510)},
{"T3511", ToJson(v.t3511)},
{"T3512", ToJson(v.t3512)},
{"T3516", ToJson(v.t3516)},
{"T3517", ToJson(v.t3517)},
{"T3519", ToJson(v.t3519)},
{"T3520", ToJson(v.t3520)},
{"T3521", ToJson(v.t3521)},
{"T3525", ToJson(v.t3525)},
{"T3540", ToJson(v.t3540)},
{"T3584", ToJson(v.t3584)},
{"T3585", ToJson(v.t3585)}, {"T3585", ToJson(v.t3585)},
}); });
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <app/monitor.hpp> #include <app/monitor.hpp>
#include <app/ue_ctl.hpp> #include <app/ue_ctl.hpp>
#include <array> #include <array>
#include <memory>
#include <nas/nas.hpp> #include <nas/nas.hpp>
#include <nas/timer.hpp> #include <nas/timer.hpp>
#include <utils/common_types.hpp> #include <utils/common_types.hpp>
...@@ -146,10 +147,6 @@ struct UeTimers ...@@ -146,10 +147,6 @@ struct UeTimers
nas::NasTimer t3525; /* MM - ... */ nas::NasTimer t3525; /* MM - ... */
nas::NasTimer t3540; /* MM - ... */ nas::NasTimer t3540; /* MM - ... */
nas::NasTimer t3580; /* SM - ... */
nas::NasTimer t3581; /* SM - ... */
nas::NasTimer t3582; /* SM - ... */
nas::NasTimer t3583; /* SM - ... */
nas::NasTimer t3584; /* SM - ... */ nas::NasTimer t3584; /* SM - ... */
nas::NasTimer t3585; /* SM - ... */ nas::NasTimer t3585; /* SM - ... */
...@@ -239,6 +236,12 @@ enum class EPsState ...@@ -239,6 +236,12 @@ enum class EPsState
MODIFICATION_PENDING MODIFICATION_PENDING
}; };
enum class EPtState
{
INACTIVE,
PENDING,
};
struct PduSession struct PduSession
{ {
static constexpr const int MIN_ID = 1; static constexpr const int MIN_ID = 1;
...@@ -268,7 +271,10 @@ struct ProcedureTransaction ...@@ -268,7 +271,10 @@ struct ProcedureTransaction
static constexpr const int MIN_ID = 1; static constexpr const int MIN_ID = 1;
static constexpr const int MAX_ID = 254; static constexpr const int MAX_ID = 254;
bool isUsed{}; EPtState state{};
std::unique_ptr<nas::NasTimer> timer{};
std::unique_ptr<nas::SmMessage> message{};
int psi{};
}; };
enum class EConnectionIdentifier enum class EConnectionIdentifier
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment