mirror of https://github.com/PentHertz/srsLTE.git
Added option to save NGAP pcaps.
This commit is contained in:
parent
a4e3d6144f
commit
5e22e42762
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_NGAP_PCAP_H
|
||||
#define SRSRAN_NGAP_PCAP_H
|
||||
|
||||
#include "srsran/common/pcap.h"
|
||||
#include <string>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
class ngap_pcap
|
||||
{
|
||||
public:
|
||||
ngap_pcap();
|
||||
ngap_pcap(const ngap_pcap& other) = delete;
|
||||
ngap_pcap& operator=(const ngap_pcap& other) = delete;
|
||||
ngap_pcap(ngap_pcap&& other) = delete;
|
||||
ngap_pcap& operator=(ngap_pcap&& other) = delete;
|
||||
|
||||
void enable();
|
||||
void open(const char* filename_);
|
||||
void close();
|
||||
void write_ngap(uint8_t* pdu, uint32_t pdu_len_bytes);
|
||||
|
||||
private:
|
||||
bool enable_write = false;
|
||||
std::string filename;
|
||||
FILE* pcap_file = nullptr;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_NAS_PCAP_H
|
|
@ -24,6 +24,7 @@
|
|||
#define UDP_DLT 149 // UDP needs to be selected as protocol
|
||||
#define S1AP_LTE_DLT 150
|
||||
#define NAS_5G_DLT 151
|
||||
#define NGAP_5G_DLT 152
|
||||
|
||||
/* This structure gets written to the start of the file */
|
||||
typedef struct pcap_hdr_s {
|
||||
|
@ -180,6 +181,12 @@ typedef struct S1AP_Context_Info_s {
|
|||
unsigned char dummy;
|
||||
} S1AP_Context_Info_t;
|
||||
|
||||
/* Context information for every S1AP PDU that will be logged */
|
||||
typedef struct NGAP_Context_Info_s {
|
||||
// No Context yet
|
||||
unsigned char dummy;
|
||||
} NGAP_Context_Info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -204,6 +211,9 @@ int LTE_PCAP_RLC_WritePDU(FILE* fd, RLC_Context_Info_t* context, const unsigned
|
|||
/* Write an individual S1AP PDU (PCAP packet header + s1ap-context + s1ap-pdu) */
|
||||
int LTE_PCAP_S1AP_WritePDU(FILE* fd, S1AP_Context_Info_t* context, const unsigned char* PDU, unsigned int length);
|
||||
|
||||
/* Write an individual S1AP PDU (PCAP packet header + s1ap-context + s1ap-pdu) */
|
||||
int LTE_PCAP_NGAP_WritePDU(FILE* fd, NGAP_Context_Info_t* context, const unsigned char* PDU, unsigned int length);
|
||||
|
||||
/* Write an individual NR MAC PDU (PCAP packet header + UDP header + nr-mac-context + mac-pdu) */
|
||||
int NR_PCAP_MAC_UDP_WritePDU(FILE* fd, mac_nr_context_info_t* context, const unsigned char* PDU, unsigned int length);
|
||||
int NR_PCAP_PACK_MAC_CONTEXT_TO_BUFFER(mac_nr_context_info_t* context, uint8_t* buffer, unsigned int length);
|
||||
|
|
|
@ -27,6 +27,7 @@ set(SOURCES arch_select.cc
|
|||
rrc_common.cc
|
||||
rlc_pcap.cc
|
||||
s1ap_pcap.cc
|
||||
ngap_pcap.cc
|
||||
security.cc
|
||||
standard_streams.cc
|
||||
thread_pool.cc
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/common/ngap_pcap.h"
|
||||
#include "srsran/common/pcap.h"
|
||||
#include "srsran/srsran.h"
|
||||
#include "srsran/support/emergency_handlers.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
/// Try to flush the contents of the pcap class before the application is killed.
|
||||
static void emergency_cleanup_handler(void* data)
|
||||
{
|
||||
reinterpret_cast<ngap_pcap*>(data)->close();
|
||||
}
|
||||
|
||||
ngap_pcap::ngap_pcap()
|
||||
{
|
||||
add_emergency_cleanup_handler(emergency_cleanup_handler, this);
|
||||
}
|
||||
|
||||
void ngap_pcap::enable()
|
||||
{
|
||||
enable_write = true;
|
||||
}
|
||||
void ngap_pcap::open(const char* filename_)
|
||||
{
|
||||
filename = filename_;
|
||||
pcap_file = DLT_PCAP_Open(NGAP_5G_DLT, filename.c_str());
|
||||
enable_write = true;
|
||||
}
|
||||
void ngap_pcap::close()
|
||||
{
|
||||
if (!enable_write) {
|
||||
return;
|
||||
}
|
||||
fprintf(stdout, "Saving NGAP PCAP file (DLT=%d) to %s\n", NGAP_5G_DLT, filename.c_str());
|
||||
DLT_PCAP_Close(pcap_file);
|
||||
}
|
||||
|
||||
void ngap_pcap::write_ngap(uint8_t* pdu, uint32_t pdu_len_bytes)
|
||||
{
|
||||
if (enable_write) {
|
||||
NGAP_Context_Info_t context;
|
||||
if (pdu) {
|
||||
LTE_PCAP_NGAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srsran
|
|
@ -336,6 +336,34 @@ int LTE_PCAP_S1AP_WritePDU(FILE* fd, S1AP_Context_Info_t* context, const unsigne
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Write an individual PDU (PCAP packet header + s1ap-context + s1ap-pdu) */
|
||||
int LTE_PCAP_NGAP_WritePDU(FILE* fd, NGAP_Context_Info_t* context, const unsigned char* PDU, unsigned int length)
|
||||
{
|
||||
pcaprec_hdr_t packet_header;
|
||||
|
||||
/* Can't write if file wasn't successfully opened */
|
||||
if (fd == NULL) {
|
||||
printf("Error: Can't write to empty file handle\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
/* PCAP Header */
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
packet_header.ts_sec = t.tv_sec;
|
||||
packet_header.ts_usec = t.tv_usec;
|
||||
packet_header.incl_len = length;
|
||||
packet_header.orig_len = length;
|
||||
|
||||
/***************************************************************/
|
||||
/* Now write everything to the file */
|
||||
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd);
|
||||
fwrite(PDU, 1, length, fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* API functions for writing MAC-NR PCAP files *
|
||||
**************************************************************************/
|
||||
|
@ -443,4 +471,4 @@ int NR_PCAP_MAC_UDP_WritePDU(FILE* fd, mac_nr_context_info_t* context, const uns
|
|||
fwrite(PDU, 1, length, fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,6 +137,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("pcap.nr_filename", bpo::value<string>(&args->nr_stack.mac.pcap.filename)->default_value("/tmp/enb_mac_nr.pcap"), "NR MAC layer capture filename")
|
||||
("pcap.s1ap_enable", bpo::value<bool>(&args->stack.s1ap_pcap.enable)->default_value(false), "Enable S1AP packet captures for wireshark")
|
||||
("pcap.s1ap_filename", bpo::value<string>(&args->stack.s1ap_pcap.filename)->default_value("/tmp/enb_s1ap.pcap"), "S1AP layer capture filename")
|
||||
("pcap.ngap_enable", bpo::value<bool>(&args->nr_stack.ngap_pcap.enable)->default_value(false), "Enable NGAP packet captures for wireshark")
|
||||
("pcap.ngap_filename", bpo::value<string>(&args->nr_stack.ngap_pcap.filename)->default_value("/tmp/enb_ngap.pcap"), "NGAP layer capture filename")
|
||||
("pcap.mac_net_enable", bpo::value<bool>(&args->stack.mac_pcap_net.enable)->default_value(false), "Enable MAC network captures")
|
||||
("pcap.bind_ip", bpo::value<string>(&args->stack.mac_pcap_net.bind_ip)->default_value("0.0.0.0"), "Bind IP address for MAC network trace")
|
||||
("pcap.bind_port", bpo::value<uint16_t>(&args->stack.mac_pcap_net.bind_port)->default_value(5687), "Bind port for MAC network trace")
|
||||
|
@ -260,6 +262,14 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("scheduler.nr_pusch_mcs", bpo::value<int>(&args->nr_stack.mac.sched_cfg.fixed_ul_mcs)->default_value(28), "Fixed NR UL MCS (-1 for dynamic).")
|
||||
("expert.nr_pusch_max_its", bpo::value<uint32_t>(&args->phy.nr_pusch_max_its)->default_value(10), "Maximum number of LDPC iterations for NR.")
|
||||
|
||||
//NGAP section
|
||||
("gnb.enb_id", bpo::value<uint32_t>(&args->nr_stack.ngap.gnb_id)->default_value(0), "gNodeB ID")
|
||||
("gnb.name", bpo::value<string>(&args->nr_stack.ngap.gnb_name)->default_value("srsgnb01"), "gNodeB Name")
|
||||
("gnb.amf_addr", bpo::value<string>(&args->nr_stack.ngap.amf_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connection")
|
||||
("gnb.gtp_bind_addr", bpo::value<string>(&args->nr_stack.ngap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection")
|
||||
("gnb.gtp_advertise_addr", bpo::value<string>(&args->nr_stack.ngap.gtp_advertise_addr)->default_value(""), "IP address of eNB to advertise for DL GTP-U Traffic")
|
||||
("gnb.ngc_bind_addr", bpo::value<string>(&args->nr_stack.ngap.ngc_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for S1AP connection")
|
||||
|
||||
// VNF params
|
||||
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("gnb"), "VNF instance type [gnb,ue].")
|
||||
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface.")
|
||||
|
@ -336,6 +346,12 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
if (!srsran::string_to_mnc(mnc, &args->stack.s1ap.mnc)) {
|
||||
cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl;
|
||||
}
|
||||
if (!srsran::string_to_mcc(mcc, &args->nr_stack.ngap.mcc)) {
|
||||
cout << "Error parsing enb.mcc:" << mcc << " - must be a 3-digit string." << endl;
|
||||
}
|
||||
if (!srsran::string_to_mnc(mnc, &args->nr_stack.ngap.mnc)) {
|
||||
cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl;
|
||||
}
|
||||
|
||||
if (args->stack.embms.enable) {
|
||||
if (args->stack.mac.sched.max_nof_ctrl_symbols == 3) {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "srsenb/hdr/stack/enb_stack_base.h"
|
||||
#include "srsran/interfaces/gnb_interfaces.h"
|
||||
|
||||
#include "srsran/common/ngap_pcap.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
class ngap;
|
||||
|
@ -36,6 +38,7 @@ struct gnb_stack_args_t {
|
|||
stack_log_args_t log;
|
||||
mac_nr_args_t mac;
|
||||
ngap_args_t ngap;
|
||||
pcap_args_t ngap_pcap;
|
||||
};
|
||||
|
||||
class gnb_stack_nr final : public srsenb::enb_stack_base,
|
||||
|
@ -129,6 +132,8 @@ private:
|
|||
srslog::basic_logger& gtpu_logger;
|
||||
srslog::basic_logger& stack_logger;
|
||||
|
||||
srsran::ngap_pcap ngap_pcap;
|
||||
|
||||
// task scheduling
|
||||
static const int STACK_MAIN_THREAD_PRIO = 4;
|
||||
srsran::task_scheduler task_sched;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/common/network_utils.h"
|
||||
#include "srsran/common/ngap_pcap.h"
|
||||
#include "srsran/common/stack_procedure.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/common/task_scheduler.h"
|
||||
|
@ -70,10 +71,13 @@ public:
|
|||
|
||||
// Stack interface
|
||||
bool
|
||||
handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags);
|
||||
handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags);
|
||||
void get_metrics(ngap_metrics_t& m);
|
||||
void get_args(ngap_args_t& args_);
|
||||
|
||||
// PCAP
|
||||
void start_pcap(srsran::ngap_pcap* pcap_);
|
||||
|
||||
private:
|
||||
static const int AMF_PORT = 38412;
|
||||
static const int ADDR_FAMILY = AF_INET;
|
||||
|
@ -128,6 +132,9 @@ private:
|
|||
// TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request
|
||||
bool handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
|
||||
|
||||
// PCAP
|
||||
srsran::ngap_pcap* pcap = nullptr;
|
||||
|
||||
class user_list
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -104,6 +104,11 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_,
|
|||
gtpu_args.mme_addr = args.ngap.amf_addr;
|
||||
gtpu_args.gtp_bind_addr = args.ngap.gtp_bind_addr;
|
||||
gtpu->init(gtpu_args, &pdcp);
|
||||
|
||||
if (args.ngap_pcap.enable) {
|
||||
ngap_pcap.open(args.ngap_pcap.filename.c_str());
|
||||
ngap->start_pcap(&ngap_pcap);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add SDAP
|
||||
|
@ -231,4 +236,4 @@ void gnb_stack_nr::rach_detected(const rach_info_t& rach_info)
|
|||
mac.rach_detected(rach_info);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -371,11 +371,10 @@ bool ngap::handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu,
|
|||
|
||||
bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu)
|
||||
{
|
||||
// TODO:
|
||||
// Save message to PCAP
|
||||
// if (pcap != nullptr) {
|
||||
// pcap->write_ngap(pdu->msg, pdu->N_bytes);
|
||||
// }
|
||||
if (pcap != nullptr) {
|
||||
pcap->write_ngap(pdu->msg, pdu->N_bytes);
|
||||
}
|
||||
|
||||
ngap_pdu_c rx_pdu;
|
||||
asn1::cbit_ref bref(pdu->msg, pdu->N_bytes);
|
||||
|
@ -696,6 +695,11 @@ bool ngap::sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t
|
|||
}
|
||||
buf->N_bytes = bref.distance_bytes();
|
||||
|
||||
// Save message to PCAP
|
||||
if (pcap != nullptr) {
|
||||
pcap->write_ngap(buf->msg, buf->N_bytes);
|
||||
}
|
||||
|
||||
if (rnti != SRSRAN_INVALID_RNTI) {
|
||||
logger.info(buf->msg, buf->N_bytes, "Tx NGAP SDU, %s, rnti=0x%x", procedure_name, rnti);
|
||||
} else {
|
||||
|
@ -794,4 +798,11 @@ std::string ngap::get_cause(const cause_c& c)
|
|||
return cause;
|
||||
}
|
||||
|
||||
/*
|
||||
* PCAP
|
||||
*/
|
||||
void ngap::start_pcap(srsran::ngap_pcap* pcap_)
|
||||
{
|
||||
pcap = pcap_;
|
||||
}
|
||||
} // namespace srsenb
|
||||
|
|
Loading…
Reference in New Issue