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)
m_ueMap[ue].ueId = ue;
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)
......@@ -164,7 +164,7 @@ void GnbMrTask::onUeReleased(int ue, rls::ECause cause)
}
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)
......
......@@ -15,41 +15,41 @@ namespace nas
{
NasTimer::NasTimer(int timerCode, bool isMmTimer, int defaultInterval)
: timerCode(timerCode), mmTimer(isMmTimer), interval(defaultInterval), startMillis(0), running(false),
expiryCount(0), _lastDebugPrintMs(0)
: m_code(timerCode), m_isMm(isMmTimer), m_interval(defaultInterval), m_startMillis(0), m_isRunning(false),
m_expiryCount(0), m_lastDebugPrintMs(0)
{
}
bool NasTimer::isRunning() const
{
return running;
return m_isRunning;
}
int NasTimer::getCode() const
{
return timerCode;
return m_code;
}
bool NasTimer::isMmTimer() const
{
return mmTimer;
return m_isMm;
}
void NasTimer::start(bool clearExpiryCount)
{
if (clearExpiryCount)
resetExpiryCount();
startMillis = utils::CurrentTimeMillis();
running = true;
m_startMillis = utils::CurrentTimeMillis();
m_isRunning = true;
}
void NasTimer::start(const nas::IEGprsTimer2 &v, bool clearExpiryCount)
{
if (clearExpiryCount)
resetExpiryCount();
interval = v.value;
startMillis = utils::CurrentTimeMillis();
running = true;
m_interval = v.value;
m_startMillis = utils::CurrentTimeMillis();
m_isRunning = true;
}
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)
secs = val * 60 * 60 * 320;
interval = secs;
startMillis = utils::CurrentTimeMillis();
running = true;
m_interval = secs;
m_startMillis = utils::CurrentTimeMillis();
m_isRunning = true;
}
void NasTimer::stop(bool clearExpiryCount)
......@@ -85,31 +85,31 @@ void NasTimer::stop(bool clearExpiryCount)
if (clearExpiryCount)
resetExpiryCount();
if (running)
if (m_isRunning)
{
startMillis = utils::CurrentTimeMillis();
running = false;
m_startMillis = utils::CurrentTimeMillis();
m_isRunning = false;
}
}
bool NasTimer::performTick()
{
if (running)
if (m_isRunning)
{
long currentMs = utils::CurrentTimeMillis();
long deltaSec = (currentMs - startMillis) / 1000LL;
long remainingSec = interval - deltaSec;
long deltaSec = (currentMs - m_startMillis) / 1000LL;
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);
}
if (remainingSec <= 0LL)
{
stop(false);
expiryCount++;
m_expiryCount++;
return true;
}
}
......@@ -118,26 +118,26 @@ bool NasTimer::performTick()
int NasTimer::getInterval() const
{
return interval;
return m_interval;
}
int NasTimer::getRemaining() const
{
if (!running)
if (!m_isRunning)
return 0;
int elapsed = static_cast<int>((utils::CurrentTimeMillis() - startMillis) / 1000LL);
return std::max(interval - elapsed, 0);
int elapsed = static_cast<int>((utils::CurrentTimeMillis() - m_startMillis) / 1000LL);
return std::max(m_interval - elapsed, 0);
}
void NasTimer::resetExpiryCount()
{
expiryCount = 0;
m_expiryCount = 0;
}
int NasTimer::getExpiryCount() const
{
return expiryCount;
return m_expiryCount;
}
Json ToJson(const NasTimer &v)
......
......@@ -18,15 +18,15 @@ namespace nas
class NasTimer
{
private:
const int timerCode;
const bool mmTimer;
const int m_code;
const bool m_isMm;
int interval;
long startMillis;
bool running;
int expiryCount;
int m_interval;
long m_startMillis;
bool m_isRunning;
int m_expiryCount;
long _lastDebugPrintMs;
long m_lastDebugPrintMs;
public:
NasTimer(int timerCode, bool isMmTimer, int defaultInterval);
......
......@@ -74,9 +74,7 @@ void NasTask::onLoop()
if (w->timer->isMmTimer())
mm->handleNasEvent(*w);
else
{
// TODO, handle SM timer
}
sm->handleNasEvent(*w);
break;
case NwUeNasToNas::ESTABLISH_INITIAL_SESSIONS:
sm->establishInitialSessions();
......@@ -147,18 +145,12 @@ void NasTask::performTick()
sendExpireMsg(&timers.t3525);
if (timers.t3540.performTick())
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())
sendExpireMsg(&timers.t3584);
if (timers.t3585.performTick())
sendExpireMsg(&timers.t3585);
sm->onTimerTick();
}
} // namespace nr::ue
\ No newline at end of file
......@@ -48,7 +48,7 @@ int NasSm::allocateProcedureTransactionId()
int id = -1;
for (int i = ProcedureTransaction::MIN_ID; i <= ProcedureTransaction::MAX_ID; i++)
{
if (!arr[i].isUsed)
if (arr[i].state == EPtState::INACTIVE)
{
id = i;
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)
}
/* Set relevant fields of the PS description */
auto ps = m_pduSessions[psi];
auto &ps = m_pduSessions[psi];
ps->psState = EPsState::ACTIVE_PENDING;
ps->sessionType = config.type;
ps->apn = config.apn;
......@@ -103,22 +103,26 @@ void NasSm::sendEstablishmentRequest(const SessionConfig &config)
iePco.options = opt.encode();
/* Prepare the establishment request message */
nas::PduSessionEstablishmentRequest req{};
req.pti = pti;
req.pduSessionId = static_cast<nas::EPduSessionIdentity>(psi);
req.integrityProtectionMaximumDataRate = MakeIntegrityMaxRate(m_base->config->integrityMaxRate);
req.pduSessionType = nas::IEPduSessionType{};
req.pduSessionType->pduSessionType = nas::EPduSessionType::IPV4;
req.sscMode = nas::IESscMode{};
req.sscMode->sscMode = nas::ESscMode::SSC_MODE_1;
req.extendedProtocolConfigurationOptions = std::move(iePco);
req.smCapability = MakeSmCapability();
/* Start T3580 */
m_timers->t3580.start();
auto req = std::make_unique<nas::PduSessionEstablishmentRequest>();
req->pti = pti;
req->pduSessionId = static_cast<nas::EPduSessionIdentity>(psi);
req->integrityProtectionMaximumDataRate = MakeIntegrityMaxRate(m_base->config->integrityMaxRate);
req->pduSessionType = nas::IEPduSessionType{};
req->pduSessionType->pduSessionType = nas::EPduSessionType::IPV4;
req->sscMode = nas::IESscMode{};
req->sscMode->sscMode = nas::ESscMode::SSC_MODE_1;
req->extendedProtocolConfigurationOptions = std::move(iePco);
req->smCapability = MakeSmCapability();
/* Set relevant fields of the PT, and start T3580 */
auto &pt = m_procedureTransactions[pti];
pt.state = EPtState::PENDING;
pt.timer = newTransactionTimer(3580);
pt.message = std::move(req);
pt.psi = psi;
/* Send SM message */
sendSmMessage(psi, req);
sendSmMessage(psi, *pt.message);
}
void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &msg)
......@@ -129,8 +133,6 @@ void NasSm::receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishm
nas::utils::EnumToString(msg.smCause->value));
}
m_timers->t3580.stop();
freeProcedureTransactionId(msg.pti);
auto pduSession = m_pduSessions[static_cast<int>(msg.pduSessionId)];
......@@ -169,4 +171,14 @@ void NasSm::receivePduSessionEstablishmentReject(const nas::PduSessionEstablishm
// 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
\ No newline at end of file
......@@ -28,7 +28,7 @@ class NasSm
std::unique_ptr<Logger> m_logger;
NasMm *m_mm;
std::array<PduSession*, 16> m_pduSessions{};
std::array<PduSession *, 16> m_pduSessions{};
std::array<ProcedureTransaction, 255> m_procedureTransactions{};
friend class UeCmdHandler;
......@@ -67,6 +67,17 @@ class NasSm
void sendEstablishmentRequest(const SessionConfig &config);
void receivePduSessionEstablishmentAccept(const nas::PduSessionEstablishmentAccept &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
\ 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()
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),
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)
{
}
......@@ -133,11 +132,22 @@ Json ToJson(const UeConfig &v)
Json ToJson(const UeTimers &v)
{
return Json::Obj({
{"T3346", ToJson(v.t3346)}, {"T3396", ToJson(v.t3396)}, {"T3444", ToJson(v.t3444)}, {"T3445", ToJson(v.t3445)},
{"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)}, {"T3580", ToJson(v.t3580)},
{"T3581", ToJson(v.t3581)}, {"T3582", ToJson(v.t3582)}, {"T3583", ToJson(v.t3583)}, {"T3584", ToJson(v.t3584)},
{"T3346", ToJson(v.t3346)},
{"T3396", ToJson(v.t3396)},
{"T3444", ToJson(v.t3444)},
{"T3445", ToJson(v.t3445)},
{"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)},
});
}
......
......@@ -11,6 +11,7 @@
#include <app/monitor.hpp>
#include <app/ue_ctl.hpp>
#include <array>
#include <memory>
#include <nas/nas.hpp>
#include <nas/timer.hpp>
#include <utils/common_types.hpp>
......@@ -146,10 +147,6 @@ struct UeTimers
nas::NasTimer t3525; /* 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 t3585; /* SM - ... */
......@@ -239,6 +236,12 @@ enum class EPsState
MODIFICATION_PENDING
};
enum class EPtState
{
INACTIVE,
PENDING,
};
struct PduSession
{
static constexpr const int MIN_ID = 1;
......@@ -268,7 +271,10 @@ struct ProcedureTransaction
static constexpr const int MIN_ID = 1;
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
......
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