pcap: make public interfaces thread-safe and handle fopen returning nullptr

the previous patch only introduced a thread-safe queue between
PHY workers (writers) and PCAP writer thread (consumer).

However, it is also required to protect the ctor (and close()) to
prevent corrupted PCAP files.

The patch also correctly handles the case where the PCAP couldn't
be openend for writing and doesn't start the thread.
master
Andre Puschmann 4 years ago
parent 02b0f251aa
commit 78b07daf3b

@ -19,9 +19,9 @@
#include "srslte/common/logmap.h" #include "srslte/common/logmap.h"
#include "srslte/common/pcap.h" #include "srslte/common/pcap.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include <mutex>
#include <stdint.h> #include <stdint.h>
#include <thread> #include <thread>
namespace srslte { namespace srslte {
class mac_pcap : srslte::thread class mac_pcap : srslte::thread
{ {
@ -71,6 +71,7 @@ private:
unique_byte_buffer_t pdu; unique_byte_buffer_t pdu;
} pcap_pdu_t; } pcap_pdu_t;
block_queue<pcap_pdu_t> queue; block_queue<pcap_pdu_t> queue;
std::mutex mutex;
void write_pdu(pcap_pdu_t& pdu); void write_pdu(pcap_pdu_t& pdu);
void run_thread() final; void run_thread() final;

@ -26,17 +26,24 @@ mac_pcap::~mac_pcap()
void mac_pcap::enable(bool enable_) void mac_pcap::enable(bool enable_)
{ {
std::lock_guard<std::mutex> lock(mutex);
running = enable_; running = enable_;
} }
uint32_t mac_pcap::open(const char* filename, uint32_t ue_id_) uint32_t mac_pcap::open(const char* filename, uint32_t ue_id_)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (pcap_file != nullptr) { if (pcap_file != nullptr) {
log->error("PCAP writer already running. Close first.\n"); log->error("PCAP writer already running. Close first.\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
pcap_file = LTE_PCAP_Open(MAC_LTE_DLT, filename); pcap_file = LTE_PCAP_Open(MAC_LTE_DLT, filename);
if (pcap_file == nullptr) {
log->error("Couldn't open file to write PCAP\n");
return SRSLTE_ERROR;
}
ue_id = ue_id_; ue_id = ue_id_;
running = true; running = true;
@ -48,6 +55,8 @@ uint32_t mac_pcap::open(const char* filename, uint32_t ue_id_)
uint32_t mac_pcap::close() uint32_t mac_pcap::close()
{ {
{
std::lock_guard<std::mutex> lock(mutex);
if (running == false || pcap_file == nullptr) { if (running == false || pcap_file == nullptr) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -56,13 +65,17 @@ uint32_t mac_pcap::close()
running = false; running = false;
pcap_pdu_t pdu = {}; pcap_pdu_t pdu = {};
queue.push(std::move(pdu)); queue.push(std::move(pdu));
}
wait_thread_finish(); wait_thread_finish();
// close file handle // close file handle
{
std::lock_guard<std::mutex> lock(mutex);
srslte::console("Saving MAC PCAP file\n"); srslte::console("Saving MAC PCAP file\n");
LTE_PCAP_Close(pcap_file); LTE_PCAP_Close(pcap_file);
pcap_file = nullptr; pcap_file = nullptr;
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -79,10 +92,14 @@ void mac_pcap::run_thread()
// blocking write until stopped // blocking write until stopped
while (running) { while (running) {
pcap_pdu_t pdu = queue.wait_pop(); pcap_pdu_t pdu = queue.wait_pop();
{
std::lock_guard<std::mutex> lock(mutex);
write_pdu(pdu); write_pdu(pdu);
} }
}
// write remainder of queue // write remainder of queue
std::lock_guard<std::mutex> lock(mutex);
pcap_pdu_t pdu = {}; pcap_pdu_t pdu = {};
while (queue.try_pop(&pdu)) { while (queue.try_pop(&pdu)) {
write_pdu(pdu); write_pdu(pdu);
@ -91,9 +108,11 @@ void mac_pcap::run_thread()
void mac_pcap::set_ue_id(uint16_t ue_id_) void mac_pcap::set_ue_id(uint16_t ue_id_)
{ {
std::lock_guard<std::mutex> lock(mutex);
ue_id = ue_id_; 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, void mac_pcap::pack_and_queue(uint8_t* payload,
uint32_t payload_len, uint32_t payload_len,
uint32_t reTX, uint32_t reTX,

Loading…
Cancel
Save