From 08a4ce0970d9a6af79ae64b2b1278697eb51d20a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 6 Mar 2020 17:48:12 +0000 Subject: [PATCH] Added the ability to save S1AP pcaps at the eNB. --- srsenb/enb.conf.example | 24 +++++++++++++++++------- srsenb/hdr/stack/enb_stack_base.h | 3 ++- srsenb/hdr/stack/enb_stack_lte.h | 15 ++++++++------- srsenb/hdr/stack/upper/s1ap.h | 7 ++++++- srsenb/src/main.cc | 10 +++++++--- srsenb/src/stack/enb_stack_lte.cc | 13 ++++++++++--- srsenb/src/stack/upper/s1ap.cc | 16 +++++++++++++++- 7 files changed, 65 insertions(+), 23 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 64a4d3ad2..2b1f42602 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -76,9 +76,9 @@ rx_gain = 40 ##################################################################### -# MAC-layer packet capture configuration +# Packet capture configuration # -# Packets are captured to file in the compact format decoded by +# MAC Packets are captured to file in the compact format decoded by # the Wireshark mac-lte-framed dissector and with DLT 147. # To use the dissector, edit the preferences for DLT_USER to # add an entry with DLT=147, Payload Protocol=mac-lte-framed. @@ -89,12 +89,22 @@ rx_gain = 40 # WRITE_SIB_PCAP enabled in srsenb/src/stack/mac/mac.cc if you want # SIB to be part of the MAC pcap file. # -# enable: Enable MAC layer packet captures (true/false) -# filename: File path to use for packet captures +# S1AP Packets are captured to file in the compact format decoded by +# the Wireshark s1ap dissector and with DLT 150. +# To use the dissector, edit the preferences for DLT_USER to +# add an entry with DLT=150, Payload Protocol=s1ap. +# +# mac_enable: Enable MAC layer packet captures (true/false) +# mac_filename: File path to use for packet captures +# s1ap_enable: Enable or disable the PCAP. +# s1ap_filename: File name where to save the PCAP. +# ##################################################################### [pcap] -enable = false -filename = /tmp/enb.pcap +mac_enable = false +mac_filename = /tmp/enb_mac.pcap +s1ap_enable = false +s1ap_filename = /tmp/enb_s1ap.pcap ##################################################################### # Log configuration @@ -268,4 +278,4 @@ nof_ctrl_symbols = 3 #rrc_inactivity_timer = 60000 #max_prach_offset_us = 30 #eea_pref_list = EEA0, EEA2, EEA1 -#eia_pref_list = EIA2, EIA1, EIA0 \ No newline at end of file +#eia_pref_list = EIA2, EIA1, EIA0 diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index a4c7e3cc1..c881a69af 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -56,7 +56,8 @@ typedef struct { typedef struct { mac_args_t mac; s1ap_args_t s1ap; - pcap_args_t pcap; + pcap_args_t mac_pcap; + pcap_args_t s1ap_pcap; stack_log_args_t log; embms_args_t embms; } stack_args_t; diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 5a1949474..f80e159ad 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -136,13 +136,14 @@ private: srslte::timer_handler timers; std::unique_ptr rx_sockets; - srsenb::mac mac; - srslte::mac_pcap mac_pcap; - srsenb::rlc rlc; - srsenb::pdcp pdcp; - srsenb::rrc rrc; - srsenb::gtpu gtpu; - srsenb::s1ap s1ap; + srsenb::mac mac; + srslte::mac_pcap mac_pcap; + srsenb::rlc rlc; + srsenb::pdcp pdcp; + srsenb::rrc rrc; + srsenb::gtpu gtpu; + srsenb::s1ap s1ap; + srslte::s1ap_pcap s1ap_pcap; srslte::logger* logger = nullptr; srslte::byte_buffer_pool* pool = nullptr; diff --git a/srsenb/hdr/stack/upper/s1ap.h b/srsenb/hdr/stack/upper/s1ap.h index 1ef4b026f..8013ff7fb 100644 --- a/srsenb/hdr/stack/upper/s1ap.h +++ b/srsenb/hdr/stack/upper/s1ap.h @@ -28,6 +28,7 @@ #include "srslte/common/buffer_pool.h" #include "srslte/common/common.h" #include "srslte/common/logmap.h" +#include "srslte/common/s1ap_pcap.h" #include "srslte/common/threads.h" #include "srslte/interfaces/enb_interfaces.h" @@ -85,7 +86,8 @@ public: // Stack interface bool - handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + void start_pcap(srslte::s1ap_pcap* pcap_); private: static const int MME_PORT = 36412; @@ -114,6 +116,9 @@ private: asn1::s1ap::tai_s tai; asn1::s1ap::eutran_cgi_s eutran_cgi; + // PCAP + srslte::s1ap_pcap *pcap; + asn1::s1ap::s1_setup_resp_s s1setupresponse; void build_tai_cgi(); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 4d6270b31..2bed9a231 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -90,11 +90,9 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("rf.device_args", bpo::value(&args->rf.device_args)->default_value("auto"), "Front-end device arguments") ("rf.time_adv_nsamples", bpo::value(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") - ("pcap.enable", bpo::value(&args->stack.pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") - ("pcap.filename", bpo::value(&args->stack.pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename") - ("gui.enable", bpo::value(&args->gui.enable)->default_value(false), "Enable GUI plots") + /* Log section */ ("log.rf_level", bpo::value(&args->rf.log_level), "RF log level") ("log.phy_level", bpo::value(&args->phy.log.phy_level), "PHY log level") ("log.phy_hex_limit", bpo::value(&args->phy.log.phy_hex_limit), "PHY log hex dump limit") @@ -118,6 +116,12 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("log.filename", bpo::value(&args->log.filename)->default_value("/tmp/ue.log"),"Log filename") ("log.file_max_size", bpo::value(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)") + /* PCAP */ + ("pcap.mac_enable", bpo::value(&args->stack.mac_pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") + ("pcap.mac_filename", bpo::value(&args->stack.mac_pcap.filename)->default_value("enb_mac.pcap"), "MAC layer capture filename") + ("pcap.s1ap_enable", bpo::value(&args->stack.s1ap_pcap.enable)->default_value(false), "Enable S1AP packet captures for wireshark") + ("pcap.s1ap_filename", bpo::value(&args->stack.s1ap_pcap.filename)->default_value("enb_s1ap.pcap"), "S1AP layer capture filename") + /* MCS section */ ("scheduler.pdsch_mcs", bpo::value(&args->stack.mac.sched.pdsch_mcs)->default_value(-1), "Optional fixed PDSCH MCS (ignores reported CQIs if specified)") ("scheduler.pdsch_max_mcs", bpo::value(&args->stack.mac.sched.pdsch_max_mcs)->default_value(-1), "Optional PDSCH MCS limit") diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 6035a80eb..55cb1c2a1 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -97,10 +97,14 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) stack_log.set_hex_limit(128); // Set up pcap and trace - if (args.pcap.enable) { - mac_pcap.open(args.pcap.filename.c_str()); + if (args.mac_pcap.enable) { + mac_pcap.open(args.mac_pcap.filename.c_str()); mac.start_pcap(&mac_pcap); } + if (args.s1ap_pcap.enable) { + s1ap_pcap.open(args.s1ap_pcap.filename.c_str()); + s1ap.start_pcap(&s1ap_pcap); + } // Init Rx socket handler rx_sockets.reset(new srslte::rx_multisocket_handler("ENBSOCKETS", &stack_log)); @@ -156,9 +160,12 @@ void enb_stack_lte::stop_impl() pdcp.stop(); rrc.stop(); - if (args.pcap.enable) { + if (args.mac_pcap.enable) { mac_pcap.close(); } + if (args.s1ap_pcap.enable) { + s1ap_pcap.close(); + } // erasing the queues is the last thing, bc we need them to call stop_impl() pending_tasks.erase_queue(sync_queue_id); diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index d3b2292a0..1e50674af 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -505,6 +505,11 @@ bool s1ap::handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu) { + // Save message to PCAP + if (pcap != nullptr) { + pcap->write_s1ap(pdu->msg, pdu->N_bytes); + } + s1ap_pdu_c rx_pdu; asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); @@ -1137,9 +1142,14 @@ bool s1ap::sctp_send_s1ap_pdu(const asn1::s1ap::s1ap_pdu_c& tx_pdu, uint32_t rnt return false; } asn1::bit_ref bref(buf->msg, buf->get_tailroom()); - tx_pdu.pack(bref); buf->N_bytes = bref.distance_bytes(); + + // Save message to PCAP + if (pcap != nullptr) { + pcap->write_s1ap(buf->msg, buf->N_bytes); + } + if (rnti > 0) { s1ap_log->info_hex(buf->msg, buf->N_bytes, "Sending %s for rnti=0x%x", procedure_name, rnti); } else { @@ -1216,6 +1226,10 @@ std::string s1ap::get_cause(const cause_c& c) return cause; } +void s1ap::start_pcap(srslte::s1ap_pcap* pcap_) +{ + pcap = pcap_; +} /******************************************************************************* /* s1ap::ue Class ********************************************************************************/