created pcap base class for main handling

This commit is contained in:
David Rupprecht 2021-02-26 11:18:57 +01:00 committed by Andre Puschmann
parent da658ed2d4
commit a58f0642cb
5 changed files with 475 additions and 409 deletions

View File

@ -13,115 +13,26 @@
#ifndef SRSLTE_MAC_PCAP_H
#define SRSLTE_MAC_PCAP_H
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h"
#include "srslte/common/pcap.h"
#include "srslte/common/threads.h"
#include "srslte/srslog/srslog.h"
#include <mutex>
#include <stdint.h>
#include <thread>
#include "srslte/common/mac_pcap_base.h"
#include "srslte/srslte.h"
namespace srslte {
class mac_pcap : srslte::thread
class mac_pcap : public mac_pcap_base
{
public:
mac_pcap();
~mac_pcap();
void enable(bool enable);
uint32_t open(std::string filename, uint32_t ue_id = 0);
uint32_t close();
void set_ue_id(uint16_t ue_id);
// EUTRA
void
write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_ranti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx);
void write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx);
// SI and BCH only for DL
void write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len);
// Sidelink
void write_sl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
// NR
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti);
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_ra_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_si_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
// NR for enb with different ue_id
// clang-format off
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
// clang-format on
private:
srslog::basic_logger& logger;
bool running = false;
uint32_t dlt = 0; // The DLT used for the PCAP file
std::string filename;
FILE* pcap_file = nullptr;
uint16_t ue_id = 0;
void pack_and_queue(uint8_t* payload,
uint32_t payload_len,
uint16_t ue_id,
uint32_t reTX,
bool crc_ok,
uint8_t cc_idx,
uint32_t tti,
uint16_t crnti_,
uint8_t direction,
uint8_t rnti_type);
void pack_and_queue_nr(uint8_t* payload,
uint32_t payload_len,
uint32_t tti,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type);
typedef struct {
// Different PCAP context for both RATs
srslte::srslte_rat_t rat;
MAC_Context_Info_t context;
mac_nr_context_info_t context_nr;
unique_byte_buffer_t pdu;
} pcap_pdu_t;
block_queue<pcap_pdu_t> queue;
std::mutex mutex;
void write_pdu(pcap_pdu_t& pdu);
void run_thread() final;
void write_pdu(srslte::mac_pcap_base::pcap_pdu_t& pdu);
FILE* pcap_file = nullptr;
uint32_t dlt = 0; // The DLT used for the PCAP file
std::string filename;
void run_thread() final;
};
} // namespace srslte
#endif // SRSLTE_MAC_PCAP_H
#endif // SRSLTE_MAC_PCAP_H

View File

@ -0,0 +1,125 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_MAC_PCAP_BASE_H
#define SRSLTE_MAC_PCAP_BASE_H
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h"
#include "srslte/common/pcap.h"
#include "srslte/common/threads.h"
#include "srslte/srslog/srslog.h"
#include <mutex>
#include <stdint.h>
#include <thread>
namespace srslte {
class mac_pcap_base : protected srslte::thread
{
public:
mac_pcap_base();
~mac_pcap_base();
void enable(bool enable);
virtual uint32_t close() = 0;
void set_ue_id(uint16_t ue_id);
// EUTRA
void
write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_ranti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx);
void write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx);
// SI and BCH only for DL
void write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
void write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len);
// Sidelink
void write_sl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
// NR
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti);
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_ra_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_si_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
// NR for enb with different ue_id
// clang-format off
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
// clang-format on
protected:
typedef struct {
// Different PCAP context for both RATs
srslte::srslte_rat_t rat;
MAC_Context_Info_t context;
mac_nr_context_info_t context_nr;
unique_byte_buffer_t pdu;
} pcap_pdu_t;
virtual void write_pdu(pcap_pdu_t& pdu) = 0;
virtual void run_thread() = 0;
std::mutex mutex;
srslog::basic_logger& logger;
bool running = false;
block_queue<pcap_pdu_t> queue;
uint16_t ue_id = 0;
private:
void pack_and_queue(uint8_t* payload,
uint32_t payload_len,
uint16_t ue_id,
uint32_t reTX,
bool crc_ok,
uint8_t cc_idx,
uint32_t tti,
uint16_t crnti_,
uint8_t direction,
uint8_t rnti_type);
void pack_and_queue_nr(uint8_t* payload,
uint32_t payload_len,
uint32_t tti,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type);
};
} // namespace srslte
#endif // SRSLTE_MAC_PCAP_BASE_H

View File

@ -20,6 +20,7 @@ set(SOURCES arch_select.cc
logmap.cc
logger_srslog_wrapper.cc
mac_pcap.cc
mac_pcap_base.cc
nas_pcap.cc
network_utils.cc
pcap.c

View File

@ -11,25 +11,16 @@
*/
#include "srslte/common/mac_pcap.h"
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include <stdint.h>
#include "srslte/common/threads.h"
namespace srslte {
mac_pcap::mac_pcap() : logger(srslog::fetch_basic_logger("MAC")), thread("PCAP_WRITER_MAC") {}
mac_pcap::mac_pcap() : mac_pcap_base() {}
mac_pcap::~mac_pcap()
{
close();
}
void mac_pcap::enable(bool enable_)
{
std::lock_guard<std::mutex> lock(mutex);
running = enable_;
}
uint32_t mac_pcap::open(std::string filename_, uint32_t ue_id_)
{
std::lock_guard<std::mutex> lock(mutex);
@ -56,6 +47,25 @@ uint32_t mac_pcap::open(std::string filename_, uint32_t ue_id_)
return SRSLTE_SUCCESS;
}
void mac_pcap::run_thread()
{
// blocking write until stopped
while (running) {
pcap_pdu_t pdu = queue.wait_pop();
{
std::lock_guard<std::mutex> lock(mutex);
write_pdu(pdu);
}
}
// write remainder of queue
std::lock_guard<std::mutex> lock(mutex);
pcap_pdu_t pdu = {};
while (queue.try_pop(&pdu)) {
write_pdu(pdu);
}
}
uint32_t mac_pcap::close()
{
{
@ -83,7 +93,7 @@ uint32_t mac_pcap::close()
return SRSLTE_SUCCESS;
}
void mac_pcap::write_pdu(pcap_pdu_t& pdu)
void mac_pcap::write_pdu(srslte::mac_pcap_base::pcap_pdu_t& pdu)
{
if (pdu.pdu != nullptr) {
switch (pdu.rat) {
@ -99,302 +109,4 @@ void mac_pcap::write_pdu(pcap_pdu_t& pdu)
}
}
void mac_pcap::run_thread()
{
// blocking write until stopped
while (running) {
pcap_pdu_t pdu = queue.wait_pop();
{
std::lock_guard<std::mutex> lock(mutex);
write_pdu(pdu);
}
}
// write remainder of queue
std::lock_guard<std::mutex> lock(mutex);
pcap_pdu_t pdu = {};
while (queue.try_pop(&pdu)) {
write_pdu(pdu);
}
}
void mac_pcap::set_ue_id(uint16_t ue_id_)
{
std::lock_guard<std::mutex> lock(mutex);
ue_id = ue_id_;
}
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
void mac_pcap::pack_and_queue(uint8_t* payload,
uint32_t payload_len,
uint16_t ue_id,
uint32_t reTX,
bool crc_ok,
uint8_t cc_idx,
uint32_t tti,
uint16_t crnti,
uint8_t direction,
uint8_t rnti_type)
{
if (running && payload != nullptr) {
pcap_pdu_t pdu = {};
pdu.rat = srslte::srslte_rat_t::lte;
pdu.context.radioType = FDD_RADIO;
pdu.context.direction = direction;
pdu.context.rntiType = rnti_type;
pdu.context.rnti = crnti;
pdu.context.ueid = ue_id;
pdu.context.isRetx = (uint8_t)reTX;
pdu.context.crcStatusOK = crc_ok;
pdu.context.cc_idx = cc_idx;
pdu.context.sysFrameNumber = (uint16_t)(tti / 10);
pdu.context.subFrameNumber = (uint16_t)(tti % 10);
// try to allocate PDU buffer
pdu.pdu = srslte::make_byte_buffer();
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
// copy payload into PDU buffer
memcpy(pdu.pdu->msg, payload, payload_len);
pdu.pdu->N_bytes = payload_len;
queue.push(std::move(pdu));
} else {
logger.info("Dropping PDU in PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
}
}
}
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
void mac_pcap::pack_and_queue_nr(uint8_t* payload,
uint32_t payload_len,
uint32_t tti,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type)
{
if (running && payload != nullptr) {
pcap_pdu_t pdu = {};
pdu.rat = srslte_rat_t::nr;
pdu.context_nr.radioType = FDD_RADIO;
pdu.context_nr.direction = direction;
pdu.context_nr.rntiType = rnti_type;
pdu.context_nr.rnti = crnti;
pdu.context_nr.ueid = ue_id;
pdu.context_nr.harqid = harqid;
pdu.context_nr.system_frame_number = tti / 10;
pdu.context_nr.sub_frame_number = tti % 10;
// try to allocate PDU buffer
pdu.pdu = srslte::make_byte_buffer();
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
// copy payload into PDU buffer
memcpy(pdu.pdu->msg, payload, payload_len);
pdu.pdu->N_bytes = payload_len;
queue.push(std::move(pdu));
} else {
logger.info("Dropping PDU in NR PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
}
}
}
void mac_pcap::write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap::write_dl_ranti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_pcap::write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap::write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap::write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap::write_sl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, SL_RNTI);
}
void mac_pcap::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, 0, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_pcap::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_PRNTI, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_pcap::write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_MRNTI, DIRECTION_DOWNLINK, M_RNTI);
}
void mac_pcap::write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI);
}
void mac_pcap::write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap::write_dl_crnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, crnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap::write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap::write_ul_crnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap::write_dl_ra_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_pcap::write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_pcap::write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_pcap::write_dl_si_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, SI_RNTI);
}
void mac_pcap::write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len)
{
uint8_t pdu[1024];
bzero(pdu, sizeof(pdu));
// Size is limited by PDU buffer and MAC subheader (format 1 < 128 B)
if (input_len > 128 - 7) {
logger.error("PDU too large.");
return;
}
// MAC PDU Header (Short BSR) (1:54) (Padding:remainder) [3 subheaders]
// Sub-header (lcid=Short BSR)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...1 1101 = LCID: Short BSR (0x1d)
// Sub-header (lcid=1, length=54)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...0 0001 = LCID: 1 (0x01)
// 0... .... = Format: Data length is < 128 bytes
// .011 0110 = Length: 54 (Will be dynamically updated)
// Sub-header (lcid=Padding, length is remainder)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..0. .... = Extension: 0x0
// ...1 1111 = LCID: Padding (0x1f)
uint8_t mac_hdr[] = {0x3D, 0x21, 0x36, 0x1F, 0x0C};
// Update MAC length
mac_hdr[2] = input_len + 7; // rlc_hdr (2) + pdcp_hdr (1) + MAC (4)
// AM Header (P) sn=4
// 1... .... = Frame type: Data PDU (0x1)
// .0.. .... = Re-segmentation Flag: AMD PDU (0x0)
// ..1. .... = Polling Bit: Status report is requested (0x1)
// ...0 0... = Framing Info: First byte begins a RLC SDU and last byte ends a RLC SDU (0x0)
// .... .0.. = Extension: Data field follows from the octet following the fixed part of the header (0x0)
// .... ..00 0000 0100 = Sequence Number: 4
uint8_t rlc_hdr[] = {0xA0, 0x04};
// PDCP-LTE sn=3
// 000. .... = Reserved: 0
// ...0 0011 = Seq Num: 3
uint8_t pdcp_hdr[] = {0x03};
uint8_t* pdu_ptr = pdu;
memcpy(pdu_ptr, mac_hdr, sizeof(mac_hdr));
pdu_ptr += sizeof(mac_hdr);
memcpy(pdu_ptr, rlc_hdr, sizeof(rlc_hdr));
pdu_ptr += sizeof(rlc_hdr);
memcpy(pdu_ptr, pdcp_hdr, sizeof(pdcp_hdr));
pdu_ptr += sizeof(pdcp_hdr);
memcpy(pdu_ptr, input, input_len);
pdu_ptr += input_len;
// MAC
uint8_t pad = 0x00;
for (uint32_t i = 0; i < 4; i++) {
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
}
// Pad
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
write_ul_crnti(pdu, pdu_ptr - pdu, 14931, true, 0, 0);
}
} // namespace srslte
} // namespace srslte

View File

@ -0,0 +1,317 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/common/mac_pcap_base.h"
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include <stdint.h>
namespace srslte {
mac_pcap_base::mac_pcap_base() : logger(srslog::fetch_basic_logger("MAC")), thread("PCAP_WRITER_MAC") {}
mac_pcap_base::~mac_pcap_base() {}
void mac_pcap_base::enable(bool enable_)
{
std::lock_guard<std::mutex> lock(mutex);
running = enable_;
}
void mac_pcap_base::set_ue_id(uint16_t ue_id_)
{
std::lock_guard<std::mutex> lock(mutex);
ue_id = ue_id_;
}
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
void mac_pcap_base::pack_and_queue(uint8_t* payload,
uint32_t payload_len,
uint16_t ue_id,
uint32_t reTX,
bool crc_ok,
uint8_t cc_idx,
uint32_t tti,
uint16_t crnti,
uint8_t direction,
uint8_t rnti_type)
{
if (running && payload != nullptr) {
pcap_pdu_t pdu = {};
pdu.rat = srslte::srslte_rat_t::lte;
pdu.context.radioType = FDD_RADIO;
pdu.context.direction = direction;
pdu.context.rntiType = rnti_type;
pdu.context.rnti = crnti;
pdu.context.ueid = ue_id;
pdu.context.isRetx = (uint8_t)reTX;
pdu.context.crcStatusOK = crc_ok;
pdu.context.cc_idx = cc_idx;
pdu.context.sysFrameNumber = (uint16_t)(tti / 10);
pdu.context.subFrameNumber = (uint16_t)(tti % 10);
// try to allocate PDU buffer
pdu.pdu = srslte::make_byte_buffer();
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
// copy payload into PDU buffer
memcpy(pdu.pdu->msg, payload, payload_len);
pdu.pdu->N_bytes = payload_len;
queue.push(std::move(pdu));
} else {
logger.info("Dropping PDU in PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
}
}
}
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
void mac_pcap_base::pack_and_queue_nr(uint8_t* payload,
uint32_t payload_len,
uint32_t tti,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type)
{
if (running && payload != nullptr) {
pcap_pdu_t pdu = {};
pdu.rat = srslte_rat_t::nr;
pdu.context_nr.radioType = FDD_RADIO;
pdu.context_nr.direction = direction;
pdu.context_nr.rntiType = rnti_type;
pdu.context_nr.rnti = crnti;
pdu.context_nr.ueid = ue_id;
pdu.context_nr.harqid = harqid;
pdu.context_nr.system_frame_number = tti / 10;
pdu.context_nr.sub_frame_number = tti % 10;
// try to allocate PDU buffer
pdu.pdu = srslte::make_byte_buffer();
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
// copy payload into PDU buffer
memcpy(pdu.pdu->msg, payload, payload_len);
pdu.pdu->N_bytes = payload_len;
queue.push(std::move(pdu));
} else {
logger.info("Dropping PDU in NR PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
}
}
}
void mac_pcap_base::write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap_base::write_dl_ranti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_pcap_base::write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap_base::write_ul_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap_base::write_dl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
bool crc_ok,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap_base::write_sl_crnti(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint32_t reTX,
uint32_t tti,
uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, SL_RNTI);
}
void mac_pcap_base::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, 0, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_pcap_base::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_PRNTI, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_pcap_base::write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_MRNTI, DIRECTION_DOWNLINK, M_RNTI);
}
void mac_pcap_base::write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
{
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI);
}
void mac_pcap_base::write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap_base::write_dl_crnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t crnti,
uint16_t ue_id,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, crnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap_base::write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap_base::write_ul_crnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint16_t ue_id,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap_base::write_dl_ra_rnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_pcap_base::write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_pcap_base::write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_pcap_base::write_dl_si_rnti_nr(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint16_t rnti,
uint8_t harqid,
uint32_t tti)
{
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, SI_RNTI);
}
void mac_pcap_base::write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len)
{
uint8_t pdu[1024];
bzero(pdu, sizeof(pdu));
// Size is limited by PDU buffer and MAC subheader (format 1 < 128 B)
if (input_len > 128 - 7) {
logger.error("PDU too large.");
return;
}
// MAC PDU Header (Short BSR) (1:54) (Padding:remainder) [3 subheaders]
// Sub-header (lcid=Short BSR)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...1 1101 = LCID: Short BSR (0x1d)
// Sub-header (lcid=1, length=54)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...0 0001 = LCID: 1 (0x01)
// 0... .... = Format: Data length is < 128 bytes
// .011 0110 = Length: 54 (Will be dynamically updated)
// Sub-header (lcid=Padding, length is remainder)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..0. .... = Extension: 0x0
// ...1 1111 = LCID: Padding (0x1f)
uint8_t mac_hdr[] = {0x3D, 0x21, 0x36, 0x1F, 0x0C};
// Update MAC length
mac_hdr[2] = input_len + 7; // rlc_hdr (2) + pdcp_hdr (1) + MAC (4)
// AM Header (P) sn=4
// 1... .... = Frame type: Data PDU (0x1)
// .0.. .... = Re-segmentation Flag: AMD PDU (0x0)
// ..1. .... = Polling Bit: Status report is requested (0x1)
// ...0 0... = Framing Info: First byte begins a RLC SDU and last byte ends a RLC SDU (0x0)
// .... .0.. = Extension: Data field follows from the octet following the fixed part of the header (0x0)
// .... ..00 0000 0100 = Sequence Number: 4
uint8_t rlc_hdr[] = {0xA0, 0x04};
// PDCP-LTE sn=3
// 000. .... = Reserved: 0
// ...0 0011 = Seq Num: 3
uint8_t pdcp_hdr[] = {0x03};
uint8_t* pdu_ptr = pdu;
memcpy(pdu_ptr, mac_hdr, sizeof(mac_hdr));
pdu_ptr += sizeof(mac_hdr);
memcpy(pdu_ptr, rlc_hdr, sizeof(rlc_hdr));
pdu_ptr += sizeof(rlc_hdr);
memcpy(pdu_ptr, pdcp_hdr, sizeof(pdcp_hdr));
pdu_ptr += sizeof(pdcp_hdr);
memcpy(pdu_ptr, input, input_len);
pdu_ptr += input_len;
// MAC
uint8_t pad = 0x00;
for (uint32_t i = 0; i < 4; i++) {
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
}
// Pad
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
write_ul_crnti(pdu, pdu_ptr - pdu, 14931, true, 0, 0);
}
} // namespace srslte