Commit d406b7ba authored by aligungr's avatar aligungr

RLS improvements

parent a707dff4
//
// 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 "udp_task.hpp"
#include <cmath>
#include <cstdint>
#include <cstring>
#include <set>
#include <gnb/nts.hpp>
#include <utils/common.hpp>
#include <utils/constants.hpp>
#include <utils/libc_error.hpp>
static constexpr const int BUFFER_SIZE = 16384;
static constexpr const int LOOP_PERIOD = 1000;
static constexpr const int HEARTBEAT_THRESHOLD = 2000;
static constexpr const int MIN_ALLOWED_DBM = -120;
static int EstimateSimulatedDbm(const Vector3 &myPos, const Vector3 &uePos)
{
int deltaX = myPos.x - uePos.x;
int deltaY = myPos.y - uePos.y;
int deltaZ = myPos.z - uePos.z;
int distance = static_cast<int>(std::sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ));
if (distance == 0)
return -1; // 0 may be confusing for people
return -distance;
}
namespace nr::gnb
{
RlsUdpTask::RlsUdpTask(TaskBase *base, uint64_t sti, Vector3 phyLocation)
: m_sti{sti}, m_phyLocation{phyLocation}, m_lastLoop{}, m_stiToUe{}, m_ueMap{}
{
m_logger = base->logBase->makeUniqueLogger("rls");
try
{
m_server = new udp::UdpServer(base->config->portalIp, cons::PortalPort);
}
catch (const LibError &e)
{
m_logger->err("RLS failure [%s]", e.what());
quit();
return;
}
}
void RlsUdpTask::onStart()
{
}
void RlsUdpTask::onLoop()
{
auto current = utils::CurrentTimeMillis();
if (current - m_lastLoop > LOOP_PERIOD)
{
m_lastLoop = current;
heartbeatCycle(current);
}
uint8_t buffer[BUFFER_SIZE];
InetAddress peerAddress;
int size = m_server->Receive(buffer, BUFFER_SIZE, LOOP_PERIOD, peerAddress);
if (size > 0)
{
auto rlsMsg = rls::DecodeRlsMessage(OctetView{buffer, static_cast<size_t>(size)});
if (rlsMsg == nullptr)
m_logger->err("Unable to decode RLS message");
else
receiveRlsPdu(peerAddress, std::move(rlsMsg));
}
}
void RlsUdpTask::onQuit()
{
delete m_server;
}
void RlsUdpTask::receiveRlsPdu(const InetAddress &addr, std::unique_ptr<rls::RlsMessage> &&msg)
{
if (msg->msgType == rls::EMessageType::HEARTBEAT)
{
int dbm = EstimateSimulatedDbm(m_phyLocation, ((const rls::RlsHeartBeat &)*msg).simPos);
if (dbm < MIN_ALLOWED_DBM)
{
// if the simulated signal strength is such low, then ignore this message
return;
}
if (m_stiToUe.count(msg->sti))
{
int ueId = m_stiToUe[msg->sti];
m_ueMap[ueId].address = addr;
m_ueMap[ueId].lastSeen = utils::CurrentTimeMillis();
}
else
{
int ueId = static_cast<int>(m_stiToUe.size()) + 1;
m_stiToUe[msg->sti] = ueId;
m_ueMap[ueId].address = addr;
m_ueMap[ueId].lastSeen = utils::CurrentTimeMillis();
// TODO notify upper layer new UE
}
rls::RlsHeartBeatAck ack{m_sti};
ack.dbm = dbm;
sendRlsPdu(addr, ack);
return;
}
// TODO notify upper layer new message
}
void RlsUdpTask::sendRlsPdu(const InetAddress &addr, const rls::RlsMessage &msg)
{
OctetString stream;
rls::EncodeRlsMessage(msg, stream);
m_server->Send(addr, stream.data(), static_cast<size_t>(stream.length()));
}
void RlsUdpTask::heartbeatCycle(int64_t time)
{
std::set<int> lostUeId{};
std::set<uint64_t> lostSti{};
for (auto &item : m_ueMap)
{
if (time - item.second.lastSeen > HEARTBEAT_THRESHOLD)
{
lostUeId.insert(item.first);
lostSti.insert(item.second.sti);
}
}
for (uint64_t sti : lostSti)
m_stiToUe.erase(sti);
for (int ueId : lostUeId)
m_ueMap.erase(ueId);
for (int ueId : lostUeId)
{
// TODO: notify upper layer
}
}
} // namespace nr::gnb
//
// 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.
//
#pragma once
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <gnb/types.hpp>
#include <lib/rls/rls_pdu.hpp>
#include <lib/udp/server.hpp>
#include <utils/nts.hpp>
namespace nr::gnb
{
class RlsUdpTask : public NtsTask
{
private:
struct UeInfo
{
uint64_t sti{};
InetAddress address;
int64_t lastSeen{};
};
private:
std::unique_ptr<Logger> m_logger;
udp::UdpServer *m_server;
uint64_t m_sti;
Vector3 m_phyLocation;
int64_t m_lastLoop;
std::unordered_map<uint64_t, int> m_stiToUe;
std::unordered_map<int, UeInfo> m_ueMap;
public:
explicit RlsUdpTask(TaskBase *base, uint64_t sti, Vector3 phyLocation);
~RlsUdpTask() override = default;
protected:
void onStart() override;
void onLoop() override;
void onQuit() override;
private:
void receiveRlsPdu(const InetAddress &addr, std::unique_ptr<rls::RlsMessage> &&msg);
void sendRlsPdu(const InetAddress &addr, const rls::RlsMessage &msg);
void heartbeatCycle(int64_t time);
};
} // namespace nr::gnb
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