Commit 05f1c4fa authored by aligungr's avatar aligungr

GTP module refactored

parent 893a17fd
......@@ -18,7 +18,6 @@ add_subdirectory(src/gnb)
add_subdirectory(src/rlc)
add_subdirectory(src/nas)
add_subdirectory(src/rrc)
add_subdirectory(src/gtp)
add_subdirectory(src/udp)
add_subdirectory(src/app)
add_subdirectory(src/urs)
......@@ -39,7 +38,6 @@ target_link_libraries(nr-gnb utils)
target_link_libraries(nr-gnb gnb)
target_link_libraries(nr-gnb rlc)
target_link_libraries(nr-gnb rrc)
target_link_libraries(nr-gnb gtp)
target_link_libraries(nr-gnb udp)
target_link_libraries(nr-gnb app)
target_link_libraries(nr-gnb urs)
......
......@@ -14,7 +14,6 @@ target_link_libraries(gnb asn-rrc)
target_link_libraries(gnb asn-utils)
target_link_libraries(gnb rrc)
target_link_libraries(gnb udp)
target_link_libraries(gnb gtp)
target_link_libraries(gnb app)
target_link_libraries(gnb urs)
......
......@@ -6,7 +6,7 @@
// and subject to the terms and conditions defined in LICENSE file.
//
#include "encode.hpp"
#include "proto.hpp"
namespace gtp
{
......@@ -241,4 +241,175 @@ GtpMessage *DecodeGtpMessage(const OctetView &stream)
return res;
}
std::unique_ptr<PduSessionInformation> PduSessionInformation::Decode(const OctetView &stream)
{
int startIndex = stream.currentIndex();
uint8_t octet = stream.read();
int type = bits::BitRange8<4, 7>(octet);
if (type != 0 && type != 1)
return nullptr;
if (type == 0)
{
auto res = std::make_unique<DlPduSessionInformation>();
auto snp = bits::BitAt<2>(octet);
res->qmp = bits::BitAt<3>(octet);
octet = stream.read();
res->qfi = bits::BitRange8<0, 5>(octet);
res->rqi = bits::BitAt<6>(octet);
auto ppp = bits::BitAt<7>(octet);
if (ppp)
{
octet = stream.read();
res->ppi = bits::BitRange8<5, 7>(octet);
}
if (res->qmp)
res->dlSendingTs = stream.read8L();
if (snp)
res->dlQfiSeq = stream.read3I();
// Consuming padding if any. See 5.5.3.5
size_t read = stream.currentIndex() - startIndex;
if ((read - 2) % 4 != 0)
{
size_t padding = 4 - ((read - 2) % 4);
stream.readOctetString(padding);
}
return res;
}
else
{
auto res = std::make_unique<UlPduSessionInformation>();
auto snp = bits::BitAt<0>(octet);
auto ulDelay = bits::BitAt<1>(octet);
auto dlDelay = bits::BitAt<2>(octet);
res->qmp = bits::BitAt<3>(octet);
octet = stream.read();
res->qfi = bits::BitRange8<5, 7>(octet);
if (res->qmp)
{
res->dlSendingTsRepeated = stream.read8L();
res->dlReceivedTs = stream.read8L();
res->ulSendingTs = stream.read8L();
}
if (dlDelay)
res->dlDelayResult = stream.read4UI();
if (ulDelay)
res->ulDelayResult = stream.read4UI();
if (snp)
res->ulQfiSeq = stream.read3I();
// Consuming padding if any. See 5.5.3.5
size_t read = stream.currentIndex() - startIndex;
if ((read - 2) % 4 != 0)
{
size_t padding = 4 - ((read - 2) % 4);
stream.readOctetString(padding);
}
return res;
}
}
bool PduSessionInformation::Encode(const PduSessionInformation &pdu, OctetString &stream)
{
if (pdu.pduType != 0 && pdu.pduType != 1)
return false;
int initialLength = stream.length();
if (pdu.pduType == 0)
{
auto &dl = dynamic_cast<const DlPduSessionInformation &>(pdu);
auto snp = dl.dlQfiSeq.has_value();
stream.appendOctet(bits::Ranged8({
{4, pdu.pduType},
{1, dl.qmp},
{1, snp},
{2, 0},
}));
stream.appendOctet(bits::Ranged8({
{1, dl.ppi.has_value()},
{1, dl.rqi},
{6, dl.qfi},
}));
if (dl.ppi.has_value())
{
stream.appendOctet(bits::Ranged8({
{3, dl.ppi.value()},
{5, 0},
}));
}
if (dl.qmp)
stream.appendOctet8(dl.dlSendingTs.has_value() ? dl.dlSendingTs.value() : 0L);
if (snp)
stream.appendOctet3(dl.dlQfiSeq.value());
}
else
{
auto &ul = dynamic_cast<const UlPduSessionInformation &>(pdu);
auto snp = ul.ulQfiSeq.has_value();
stream.appendOctet(bits::Ranged8({
{4, pdu.pduType},
{1, ul.qmp},
{1, ul.dlDelayResult.has_value()},
{1, ul.ulDelayResult.has_value()},
{1, snp},
}));
stream.appendOctet(bits::Ranged8({
{2, 0},
{6, ul.qfi},
}));
if (ul.qmp)
{
stream.appendOctet8(!ul.dlSendingTsRepeated.has_value() ? 0 : ul.dlSendingTsRepeated.value());
stream.appendOctet8(!ul.dlReceivedTs.has_value() ? 0 : ul.dlReceivedTs.value());
stream.appendOctet8(!ul.ulSendingTs.has_value() ? 0 : ul.ulSendingTs.value());
}
if (ul.dlDelayResult.has_value())
stream.appendOctet4(ul.dlDelayResult.value());
if (ul.ulDelayResult.has_value())
stream.appendOctet4(ul.ulDelayResult.value());
if (snp)
stream.appendOctet3(ul.ulQfiSeq.value());
}
// Adjusting padding. See 5.5.3.5
int written = stream.length() - initialLength;
if ((written - 2) % 4 != 0)
{
int padding = 4 - ((written - 2) % 4);
stream.appendPadding(padding);
}
return true;
}
} // namespace gtp
\ No newline at end of file
......@@ -13,6 +13,7 @@
#include <optional>
#include <utils/octet_string.hpp>
#include <utils/octet_view.hpp>
#include <vector>
namespace gtp
{
......@@ -130,4 +131,25 @@ struct PduSessionContainerExtHeader : GtpExtHeader
}
};
struct GtpMessage
{
// GTP Message Types. (Only GTP-U included)
static constexpr const uint8_t MT_ECHO_REQUEST = 1;
static constexpr const uint8_t MT_ECHO_RESPONSE = 2;
static constexpr const uint8_t MT_ERROR_INDICATION = 26;
static constexpr const uint8_t MT_SUPPORTED_EXT_HEADERS_NOTIFICATION = 31;
static constexpr const uint8_t MT_END_MARKER = 254;
static constexpr const uint8_t MT_G_PDU = 255;
uint8_t msgType;
uint32_t teid;
std::optional<uint16_t> seq;
std::optional<uint8_t> nPduNum;
std::vector<std::unique_ptr<GtpExtHeader>> extHeaders;
OctetString payload;
};
bool EncodeGtpMessage(const GtpMessage &msg, OctetString &stream);
GtpMessage *DecodeGtpMessage(const OctetView &stream);
} // namespace gtp
......@@ -10,8 +10,7 @@
#include <asn/ngap/ASN_NGAP_QosFlowSetupRequestItem.h>
#include <gnb/mr/task.hpp>
#include <gtp/encode.hpp>
#include <gtp/message.hpp>
#include <gnb/gtp/proto.hpp>
#include <utils/constants.hpp>
#include <utils/libc_error.hpp>
......
cmake_minimum_required(VERSION 3.17)
file(GLOB HDR_FILES *.hpp)
file(GLOB SRC_FILES *.cpp)
add_library(gtp ${HDR_FILES} ${SRC_FILES})
target_compile_options(gtp PRIVATE -Wall -Wextra -pedantic -Wno-unused-parameter)
target_link_libraries(gtp utils)
//
// 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 "message.hpp"
namespace gtp
{
bool EncodeGtpMessage(const GtpMessage &msg, OctetString &stream);
GtpMessage *DecodeGtpMessage(const OctetView &stream);
} // namespace gtp
//
// 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 "ext_header.hpp"
namespace gtp
{
std::unique_ptr<PduSessionInformation> gtp::PduSessionInformation::Decode(const OctetView &stream)
{
int startIndex = stream.currentIndex();
uint8_t octet = stream.read();
int type = bits::BitRange8<4, 7>(octet);
if (type != 0 && type != 1)
return nullptr;
if (type == 0)
{
auto res = std::make_unique<DlPduSessionInformation>();
auto snp = bits::BitAt<2>(octet);
res->qmp = bits::BitAt<3>(octet);
octet = stream.read();
res->qfi = bits::BitRange8<0, 5>(octet);
res->rqi = bits::BitAt<6>(octet);
auto ppp = bits::BitAt<7>(octet);
if (ppp)
{
octet = stream.read();
res->ppi = bits::BitRange8<5, 7>(octet);
}
if (res->qmp)
res->dlSendingTs = stream.read8L();
if (snp)
res->dlQfiSeq = stream.read3I();
// Consuming padding if any. See 5.5.3.5
size_t read = stream.currentIndex() - startIndex;
if ((read - 2) % 4 != 0)
{
size_t padding = 4 - ((read - 2) % 4);
stream.readOctetString(padding);
}
return res;
}
else
{
auto res = std::make_unique<UlPduSessionInformation>();
auto snp = bits::BitAt<0>(octet);
auto ulDelay = bits::BitAt<1>(octet);
auto dlDelay = bits::BitAt<2>(octet);
res->qmp = bits::BitAt<3>(octet);
octet = stream.read();
res->qfi = bits::BitRange8<5, 7>(octet);
if (res->qmp)
{
res->dlSendingTsRepeated = stream.read8L();
res->dlReceivedTs = stream.read8L();
res->ulSendingTs = stream.read8L();
}
if (dlDelay)
res->dlDelayResult = stream.read4UI();
if (ulDelay)
res->ulDelayResult = stream.read4UI();
if (snp)
res->ulQfiSeq = stream.read3I();
// Consuming padding if any. See 5.5.3.5
size_t read = stream.currentIndex() - startIndex;
if ((read - 2) % 4 != 0)
{
size_t padding = 4 - ((read - 2) % 4);
stream.readOctetString(padding);
}
return res;
}
}
bool PduSessionInformation::Encode(const PduSessionInformation &pdu, OctetString &stream)
{
if (pdu.pduType != 0 && pdu.pduType != 1)
return false;
int initialLength = stream.length();
if (pdu.pduType == 0)
{
auto &dl = dynamic_cast<const DlPduSessionInformation &>(pdu);
auto snp = dl.dlQfiSeq.has_value();
stream.appendOctet(bits::Ranged8({
{4, pdu.pduType},
{1, dl.qmp},
{1, snp},
{2, 0},
}));
stream.appendOctet(bits::Ranged8({
{1, dl.ppi.has_value()},
{1, dl.rqi},
{6, dl.qfi},
}));
if (dl.ppi.has_value())
{
stream.appendOctet(bits::Ranged8({
{3, dl.ppi.value()},
{5, 0},
}));
}
if (dl.qmp)
stream.appendOctet8(dl.dlSendingTs.has_value() ? dl.dlSendingTs.value() : 0L);
if (snp)
stream.appendOctet3(dl.dlQfiSeq.value());
}
else
{
auto &ul = dynamic_cast<const UlPduSessionInformation &>(pdu);
auto snp = ul.ulQfiSeq.has_value();
stream.appendOctet(bits::Ranged8({
{4, pdu.pduType},
{1, ul.qmp},
{1, ul.dlDelayResult.has_value()},
{1, ul.ulDelayResult.has_value()},
{1, snp},
}));
stream.appendOctet(bits::Ranged8({
{2, 0},
{6, ul.qfi},
}));
if (ul.qmp)
{
stream.appendOctet8(!ul.dlSendingTsRepeated.has_value() ? 0 : ul.dlSendingTsRepeated.value());
stream.appendOctet8(!ul.dlReceivedTs.has_value() ? 0 : ul.dlReceivedTs.value());
stream.appendOctet8(!ul.ulSendingTs.has_value() ? 0 : ul.ulSendingTs.value());
}
if (ul.dlDelayResult.has_value())
stream.appendOctet4(ul.dlDelayResult.value());
if (ul.ulDelayResult.has_value())
stream.appendOctet4(ul.ulDelayResult.value());
if (snp)
stream.appendOctet3(ul.ulQfiSeq.value());
}
// Adjusting padding. See 5.5.3.5
int written = stream.length() - initialLength;
if ((written - 2) % 4 != 0)
{
int padding = 4 - ((written - 2) % 4);
stream.appendPadding(padding);
}
return true;
}
} // namespace gtp
//
// 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 "message.hpp"
//
// 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 "ext_header.hpp"
#include <cstdint>
#include <memory>
#include <optional>
#include <vector>
namespace gtp
{
struct GtpMessage
{
// GTP Message Types. (Only GTP-U included)
static constexpr const uint8_t MT_ECHO_REQUEST = 1;
static constexpr const uint8_t MT_ECHO_RESPONSE = 2;
static constexpr const uint8_t MT_ERROR_INDICATION = 26;
static constexpr const uint8_t MT_SUPPORTED_EXT_HEADERS_NOTIFICATION = 31;
static constexpr const uint8_t MT_END_MARKER = 254;
static constexpr const uint8_t MT_G_PDU = 255;
uint8_t msgType;
uint32_t teid;
std::optional<uint16_t> seq;
std::optional<uint8_t> nPduNum;
std::vector<std::unique_ptr<GtpExtHeader>> extHeaders;
OctetString payload;
};
} // namespace gtp
\ No newline at end of file
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