add MAC-NR PCAP support

master
Andre Puschmann 5 years ago
parent a3932f9bea
commit 090f2b4110

@ -0,0 +1,65 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_MAC_NR_PCAP_H
#define SRSLTE_MAC_NR_PCAP_H
#include "srslte/common/pcap.h"
#include <stdint.h>
#include <string>
namespace srslte {
class mac_nr_pcap
{
public:
mac_nr_pcap();
~mac_nr_pcap();
void enable(const bool& enable_);
void open(const std::string& filename, const uint16_t& ue_id = 0);
void close();
void set_ue_id(const uint16_t& ue_id);
void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti);
void write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_ra_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_si_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
private:
bool enable_write = false;
std::string filename;
FILE* pcap_file = nullptr;
uint32_t ue_id = 0;
void pack_and_write(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint32_t tti,
uint16_t crnti_,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type);
};
} // namespace srslte
#endif // SRSLTE_MAC_NR_PCAP_H

@ -29,7 +29,7 @@
#define MAC_LTE_DLT 147 #define MAC_LTE_DLT 147
#define NAS_LTE_DLT 148 #define NAS_LTE_DLT 148
#define RLC_LTE_DLT 149 // UDP needs to be selected as protocol #define UDP_DLT 149 // UDP needs to be selected as protocol
#define S1AP_LTE_DLT 150 #define S1AP_LTE_DLT 150
/* This structure gets written to the start of the file */ /* This structure gets written to the start of the file */
@ -102,6 +102,25 @@ typedef struct NAS_Context_Info_s {
// No Context yet // No Context yet
} NAS_Context_Info_t; } NAS_Context_Info_t;
#define MAC_NR_START_STRING "mac-nr"
#define MAC_NR_PHR_TYPE2_OTHERCELL_TAG 0x05
#define MAC_NR_HARQID 0x06
/* Context information for every MAC NR PDU that will be logged */
typedef struct {
uint8_t radioType;
uint8_t direction;
uint8_t rntiType;
uint16_t rnti;
uint16_t ueid;
uint8_t harqid;
uint8_t phr_type2_othercell;
uint16_t system_frame_number;
uint8_t sub_frame_number;
uint16_t length;
} mac_nr_context_info_t;
/* RLC-LTE disector */ /* RLC-LTE disector */
@ -437,4 +456,93 @@ inline int LTE_PCAP_S1AP_WritePDU(FILE *fd, S1AP_Context_Info_t *context,
return 1; return 1;
} }
/**************************************************************************
* API functions for writing MAC-NR PCAP files *
**************************************************************************/
/* Write an individual NR MAC PDU (PCAP packet header + UDP header + nr-mac-context + mac-pdu) */
inline int NR_PCAP_MAC_WritePDU(FILE* fd, mac_nr_context_info_t* context, const unsigned char* PDU, unsigned int length)
{
char context_header[256] = {};
int offset = 0;
/* Can't write if file wasn't successfully opened */
if (fd == NULL) {
printf("Error: Can't write to empty file handle\n");
return 0;
}
// Add dummy UDP header, start with src and dest port
context_header[offset++] = 0xde;
context_header[offset++] = 0xad;
context_header[offset++] = 0xbe;
context_header[offset++] = 0xef;
// length
uint16_t tmp16 = htons(length + 31);
memcpy(context_header + offset, &tmp16, 2);
offset += 2;
// dummy CRC
context_header[offset++] = 0xde;
context_header[offset++] = 0xad;
// Start magic string
memcpy(&context_header[offset], MAC_NR_START_STRING, strlen(MAC_NR_START_STRING));
offset += strlen(MAC_NR_START_STRING);
/*****************************************************************/
/* Context information (same as written by UDP heuristic clients */
context_header[offset++] = context->radioType;
context_header[offset++] = context->direction;
context_header[offset++] = context->rntiType;
/* RNTI */
context_header[offset++] = MAC_LTE_RNTI_TAG;
tmp16 = htons(context->rnti);
memcpy(context_header + offset, &tmp16, 2);
offset += 2;
/* UEId */
context_header[offset++] = MAC_LTE_UEID_TAG;
tmp16 = htons(context->ueid);
memcpy(context_header + offset, &tmp16, 2);
offset += 2;
/* HARQID */
context_header[offset++] = MAC_NR_HARQID;
context_header[offset++] = context->harqid;
/* PHR Type2 other cell */
context_header[offset++] = MAC_NR_PHR_TYPE2_OTHERCELL_TAG;
context_header[offset++] = context->phr_type2_othercell;
/* Subframe Number and System Frame Number */
/* SFN is stored in 12 MSB and SF in 4 LSB */
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = (context->system_frame_number << 4) | context->sub_frame_number;
tmp16 = htons(tmp16);
memcpy(context_header + offset, &tmp16, 2);
offset += 2;
/* Data tag immediately preceding PDU */
context_header[offset++] = MAC_LTE_PAYLOAD_TAG;
/****************************************************************/
/* PCAP Header */
struct timeval t;
gettimeofday(&t, NULL);
pcaprec_hdr_t packet_header;
packet_header.ts_sec = t.tv_sec;
packet_header.ts_usec = t.tv_usec;
packet_header.incl_len = offset + length;
packet_header.orig_len = offset + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd);
fwrite(context_header, 1, offset, fd);
fwrite(PDU, 1, length, fd);
return 1;
}
#endif // SRSLTE_PCAP_H #endif // SRSLTE_PCAP_H

@ -0,0 +1,117 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/common/mac_nr_pcap.h"
#include "srslte/srslte.h"
#include <stdint.h>
namespace srslte {
mac_nr_pcap::mac_nr_pcap() {}
mac_nr_pcap::~mac_nr_pcap()
{
if (pcap_file) {
close();
}
}
void mac_nr_pcap::enable(const bool& enable_)
{
enable_write = enable_;
}
void mac_nr_pcap::open(const std::string& filename_, const uint16_t& ue_id_)
{
fprintf(stdout, "Opening MAC-NR PCAP with DLT=%d\n", UDP_DLT);
filename = filename_;
pcap_file = LTE_PCAP_Open(UDP_DLT, filename.c_str());
ue_id = ue_id_;
enable_write = true;
}
void mac_nr_pcap::close()
{
enable_write = false;
fprintf(stdout, "Saving MAC-NR PCAP to %s\n", filename.c_str());
LTE_PCAP_Close(pcap_file);
pcap_file = nullptr;
}
void mac_nr_pcap::set_ue_id(const uint16_t& ue_id_)
{
ue_id = ue_id_;
}
void mac_nr_pcap::pack_and_write(uint8_t* pdu,
uint32_t pdu_len_bytes,
uint32_t tti,
uint16_t crnti,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type)
{
if (enable_write) {
mac_nr_context_info_t context = {};
context.radioType = FDD_RADIO;
context.direction = direction;
context.rntiType = rnti_type;
context.rnti = crnti;
context.ueid = ue_id;
context.harqid = harqid;
context.system_frame_number = tti / 10;
context.sub_frame_number = tti % 10;
if (pdu) {
NR_PCAP_MAC_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
}
}
}
void mac_nr_pcap::write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_nr_pcap::write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_UPLINK, C_RNTI);
}
void mac_nr_pcap::write_dl_ra_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_nr_pcap::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_nr_pcap::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_nr_pcap::write_dl_si_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, SI_RNTI);
}
} // namespace srslte

@ -32,8 +32,8 @@ void rlc_pcap::enable(bool en)
} }
void rlc_pcap::open(const char* filename, uint32_t ue_id) void rlc_pcap::open(const char* filename, uint32_t ue_id)
{ {
fprintf(stdout, "Opening RLC PCAP with DLT=%d\n", RLC_LTE_DLT); fprintf(stdout, "Opening RLC PCAP with DLT=%d\n", UDP_DLT);
pcap_file = LTE_PCAP_Open(RLC_LTE_DLT, filename); pcap_file = LTE_PCAP_Open(UDP_DLT, filename);
this->ue_id = ue_id; this->ue_id = ue_id;
enable_write = true; enable_write = true;
} }

Loading…
Cancel
Save