From 28844b54ddafa0456439877022c6a5a9bb2994d4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 28 Jun 2018 21:13:41 +0100 Subject: [PATCH 01/28] Possible fix for #164. --- lib/src/common/logger_file.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index abbea8f93..999a73077 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -45,11 +45,15 @@ logger_file::~logger_file() { not_done = false; if(inited) { log(new std::string("Closing log\n")); + pthread_mutex_lock(&mutex); + pthread_cond_signal(¬_empty); // wakeup thread and let it terminate + pthread_mutex_unlock(&mutex); wait_thread_finish(); flush(); if (logfile) { fclose(logfile); } + pthread_mutex_destroy(&mutex); } } @@ -84,6 +88,10 @@ void logger_file::run_thread() { pthread_mutex_lock(&mutex); while(buffer.empty()) { pthread_cond_wait(¬_empty, &mutex); + if(not_done == false) // Thread done. Messages in buffer will be handled in flush. + { + return; + } } str_ptr s = buffer.front(); pthread_cond_signal(¬_full); From 58823b16110da71d706ce918bbb6d342d745bdc4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 28 Jun 2018 21:22:37 +0100 Subject: [PATCH 02/28] Destroying condition variable. --- lib/src/common/logger_file.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index 999a73077..e8c60dcdb 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -54,6 +54,8 @@ logger_file::~logger_file() { fclose(logfile); } pthread_mutex_destroy(&mutex); + pthread_cond_destroy(¬_empty); + pthread_cond_destroy(¬_full); } } From e2e82cc464e9f3e913fc342742ea270531f2be36 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 29 Jun 2018 11:27:12 +0100 Subject: [PATCH 03/28] Removing broadcats hack. Returning to a simple TUN insterface on the MBMS-GW. --- srsepc/src/mbms-gw/mbms-gw.cc | 61 +---------------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index a3d18a68d..3031fc1c8 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -285,8 +285,6 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) { uint8_t version; srslte::gtpu_header_t header; - in_addr_t baddr = inet_addr("172.16.0.255"); - in_addr_t saddr = inet_addr("172.16.0.254"); //Setup GTP-U header header.flags = 0x30; @@ -301,44 +299,14 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) return; } - //IP+UDP Headers + //IP Headers struct iphdr *iph = (struct iphdr *) msg->msg; - struct udphdr *udph = (struct udphdr *) (msg->msg + iph->ihl*4); if(iph->version != 4) { m_mbms_gw_log->warning("IPv6 not supported yet.\n"); return; } - //Replace Destination IP with broadcast address - iph->daddr = baddr; - - //Replace Source IP with address in same subnet - iph->saddr = saddr; - - //Replace IP cheksum - iph->check = 0; - iph->check = in_cksum((uint16_t*)msg->msg,4*(msg->msg[0] & 0x0F)); - - //Set Pseudo Header - struct pseudo_hdr phdr; - phdr.src_addr = iph->saddr; - phdr.dst_addr = iph->daddr; - phdr.protocol = IPPROTO_UDP; - phdr.placeholder = 0; - phdr.udp_len = udph->len; - - //Set Pseudo Datagram - udph->check = 0; - int psize = sizeof(struct pseudo_hdr) + ntohs(udph->len); - uint8_t * pseudo_dgram = (uint8_t*) malloc(psize); - memcpy(pseudo_dgram, &phdr,sizeof(struct pseudo_hdr)); - memcpy(pseudo_dgram+sizeof(pseudo_hdr),udph,ntohs(udph->len)); - - //Recompute UDP checksum - udph->check = in_cksum((uint16_t*) pseudo_dgram, psize); - free(pseudo_dgram); - //Write GTP-U header into packet if(!srslte::gtpu_write_header(&header, msg)) { @@ -355,31 +323,4 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) } } -uint16_t -mbms_gw::in_cksum(uint16_t *iphdr, int count) -{ - - //RFC 1071 - uint32_t sum = 0; - uint16_t padd = 0; - uint16_t result; - while(count > 1) - { - sum+= *iphdr++; - count -= 2; - } - if( count > 0 ) - { - padd = * (uint8_t *) iphdr; - sum += padd; - } - /*Fold 32-bit sum to 16-bit*/ - // while(sum>>16) - // sum = (sum & 0xffff) + (sum >> 16); - sum = (sum>>16)+(sum & 0xFFFF); - sum = sum + (sum >> 16); - result = (uint16_t) ~sum; - return result; -} - } //namespace srsepc From 4deb2510711134a0fb40cb4295cc39b942f43dff Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 3 Jul 2018 13:09:43 +0200 Subject: [PATCH 04/28] remove duplicate run-state variable in logger_file --- lib/include/srslte/common/logger_file.h | 3 +-- lib/src/common/logger_file.cc | 20 ++++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/include/srslte/common/logger_file.h b/lib/include/srslte/common/logger_file.h index f0bd5a15b..f4bfd4582 100644 --- a/lib/include/srslte/common/logger_file.h +++ b/lib/include/srslte/common/logger_file.h @@ -64,8 +64,7 @@ private: int64_t max_length; int64_t cur_length; FILE* logfile; - bool inited; - bool not_done; + bool is_running; std::string filename; pthread_cond_t not_empty; pthread_cond_t not_full; diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index e8c60dcdb..12fcbb3ba 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -34,18 +34,17 @@ using namespace std; namespace srslte{ logger_file::logger_file() - :inited(false) - ,logfile(NULL) - ,not_done(true) + :logfile(NULL) + ,is_running(false) ,cur_length(0) ,max_length(0) {} logger_file::~logger_file() { - not_done = false; - if(inited) { + if(is_running) { log(new std::string("Closing log\n")); pthread_mutex_lock(&mutex); + is_running = false; pthread_cond_signal(¬_empty); // wakeup thread and let it terminate pthread_mutex_unlock(&mutex); wait_thread_finish(); @@ -67,11 +66,11 @@ void logger_file::init(std::string file, int max_length_) { name_idx = 0; filename = file; logfile = fopen(filename.c_str(), "w"); - if(logfile==NULL) { + if(logfile == NULL) { printf("Error: could not create log file, no messages will be logged!\n"); } + is_running = true; start(-2); - inited = true; } void logger_file::log(const char *msg) { @@ -86,14 +85,11 @@ void logger_file::log(str_ptr msg) { } void logger_file::run_thread() { - while(not_done) { + while(is_running) { pthread_mutex_lock(&mutex); while(buffer.empty()) { pthread_cond_wait(¬_empty, &mutex); - if(not_done == false) // Thread done. Messages in buffer will be handled in flush. - { - return; - } + if(!is_running) return; // Thread done. Messages in buffer will be handled in flush. } str_ptr s = buffer.front(); pthread_cond_signal(¬_full); From 87fd218c72fd249728f8513228ee3c303e42de19 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 3 Jul 2018 13:17:48 +0200 Subject: [PATCH 05/28] remove unused cond variable in logger --- lib/include/srslte/common/logger_file.h | 1 - lib/src/common/logger_file.cc | 3 --- 2 files changed, 4 deletions(-) diff --git a/lib/include/srslte/common/logger_file.h b/lib/include/srslte/common/logger_file.h index f4bfd4582..956753f7a 100644 --- a/lib/include/srslte/common/logger_file.h +++ b/lib/include/srslte/common/logger_file.h @@ -67,7 +67,6 @@ private: bool is_running; std::string filename; pthread_cond_t not_empty; - pthread_cond_t not_full; pthread_mutex_t mutex; pthread_t thread; std::deque buffer; diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index 12fcbb3ba..d89dfac0c 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -54,14 +54,12 @@ logger_file::~logger_file() { } pthread_mutex_destroy(&mutex); pthread_cond_destroy(¬_empty); - pthread_cond_destroy(¬_full); } } void logger_file::init(std::string file, int max_length_) { pthread_mutex_init(&mutex, NULL); pthread_cond_init(¬_empty, NULL); - pthread_cond_init(¬_full, NULL); max_length = (int64_t)max_length_*1024; name_idx = 0; filename = file; @@ -92,7 +90,6 @@ void logger_file::run_thread() { if(!is_running) return; // Thread done. Messages in buffer will be handled in flush. } str_ptr s = buffer.front(); - pthread_cond_signal(¬_full); int n = 0; if(logfile) n = fprintf(logfile, "%s", s->c_str()); From 27dbbcca0261173fbc8f1b71ab3730fc4c245020 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 3 Jul 2018 12:48:25 +0100 Subject: [PATCH 06/28] Stripping GTPU in eNB's M1-U. --- srsenb/src/upper/gtpu.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index 334878941..83280e3c3 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -427,6 +427,9 @@ void gtpu::mch_thread::run_thread() } while (n == -1 && errno == EAGAIN); pdu->N_bytes = (uint32_t) n; + + gtpu_header_t header; + gtpu_read_header(pdu, &header); pdcp->write_sdu(SRSLTE_MRNTI, lcid, pdu); do { From 0e135adc6f3ac769ecffe5148a5e09f02bb546ae Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 3 Jul 2018 14:30:20 +0100 Subject: [PATCH 07/28] Starting to change gtpu_read_header and gtpu_write_header to lib. --- lib/include/srslte/upper/gtpu.h | 5 +- lib/src/upper/gtpu.cc | 14 ++--- srsenb/hdr/upper/gtpu.h | 31 +++-------- srsenb/src/upper/gtpu.cc | 92 +++++---------------------------- 4 files changed, 31 insertions(+), 111 deletions(-) diff --git a/lib/include/srslte/upper/gtpu.h b/lib/include/srslte/upper/gtpu.h index 3cd8a1202..24b9c5c41 100644 --- a/lib/include/srslte/upper/gtpu.h +++ b/lib/include/srslte/upper/gtpu.h @@ -29,6 +29,7 @@ #include #include "srslte/common/common.h" +#include "srslte/common/log.h" namespace srslte { @@ -58,8 +59,8 @@ typedef struct{ }gtpu_header_t; -bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header); -bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu); +bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header, srslte::log *gtpu_log); +bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu, srslte::log *gtpu_log); inline void uint8_to_uint32(uint8_t *buf, uint32_t *i) { diff --git a/lib/src/upper/gtpu.cc b/lib/src/upper/gtpu.cc index 668af8915..a8046aa4d 100644 --- a/lib/src/upper/gtpu.cc +++ b/lib/src/upper/gtpu.cc @@ -35,18 +35,18 @@ namespace srslte { * Ref: 3GPP TS 29.281 v10.1.0 Section 5 ***************************************************************************/ -bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu) +bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu, srslte::log *gtpu_log) { if(header->flags != 0x30) { - //gtpu_log->error("gtpu_write_header - Unhandled header flags: 0x%x\n", header->flags); + gtpu_log->error("gtpu_write_header - Unhandled header flags: 0x%x\n", header->flags); return false; } if(header->message_type != 0xFF) { - //gtpu_log->error("gtpu_write_header - Unhandled message type: 0x%x\n", header->message_type); + gtpu_log->error("gtpu_write_header - Unhandled message type: 0x%x\n", header->message_type); return false; } if(pdu->get_headroom() < GTPU_HEADER_LEN) { - //gtpu_log->error("gtpu_write_header - No room in PDU for header\n"); + gtpu_log->error("gtpu_write_header - No room in PDU for header\n"); return false; } @@ -66,7 +66,7 @@ bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu) return true; } -bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header) +bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header, srslte::log *gtpu_log) { uint8_t *ptr = pdu->msg; @@ -82,11 +82,11 @@ bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header) uint8_to_uint32(ptr, &header->teid); if(header->flags != 0x30) { - //gtpu_log->error("gtpu_read_header - Unhandled header flags: 0x%x\n", header->flags); + gtpu_log->error("gtpu_read_header - Unhandled header flags: 0x%x\n", header->flags); return false; } if(header->message_type != 0xFF) { - //gtpu_log->error("gtpu_read_header - Unhandled message type: 0x%x\n", header->message_type); + gtpu_log->error("gtpu_read_header - Unhandled message type: 0x%x\n", header->message_type); return false; } diff --git a/srsenb/hdr/upper/gtpu.h b/srsenb/hdr/upper/gtpu.h index 1a8d6daaa..4dc05585d 100644 --- a/srsenb/hdr/upper/gtpu.h +++ b/srsenb/hdr/upper/gtpu.h @@ -58,33 +58,25 @@ namespace srsenb { #define GTPU_HEADER_LEN 8 -typedef struct{ - uint8_t flags; // Only support 0x30 - v1, PT1 (GTP), no other flags - uint8_t message_type; // Only support 0xFF - T-PDU type - uint16_t length; - uint32_t teid; -}gtpu_header_t; - - class gtpu :public gtpu_interface_rrc ,public gtpu_interface_pdcp ,public thread { -public: - +public: + gtpu(); - + bool init(std::string gtp_bind_addr_, std::string mme_addr_, pdcp_interface_gtpu *pdcp_, srslte::log *gtpu_log_, bool enable_mbsfn = false); void stop(); - + // gtpu_interface_rrc void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t *teid_in); void rem_bearer(uint16_t rnti, uint32_t lcid); void rem_user(uint16_t rnti); - + // gtpu_interface_pdcp - void write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu); + void write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu); private: static const int THREAD_PRIO = 65; @@ -92,8 +84,6 @@ private: srslte::byte_buffer_pool *pool; bool running; bool run_enable; - - bool enable_mbsfn; std::string gtp_bind_addr; @@ -141,14 +131,7 @@ private: //Threading void run_thread(); - pthread_mutex_t mutex; - - /**************************************************************************** - * Header pack/unpack helper functions - * Ref: 3GPP TS 29.281 v10.1.0 Section 5 - ***************************************************************************/ - bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu); - bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header); + pthread_mutex_t mutex; /**************************************************************************** * TEID to RNIT/LCID helper functions diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index 83280e3c3..0f8bc3325 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -23,7 +23,7 @@ * and at http://www.gnu.org/licenses/. * */ - +#include "srslte/upper/gtpu.h" #include "srsenb/hdr/upper/gtpu.h" #include #include @@ -31,13 +31,12 @@ #include using namespace srslte; - namespace srsenb { - - gtpu::gtpu():mchthread() - { - } - + +gtpu::gtpu():mchthread() +{ +} + bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_interface_gtpu* pdcp_, srslte::log* gtpu_log_, bool enable_mbsfn) { pdcp = pdcp_; @@ -45,8 +44,8 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_ gtp_bind_addr = gtp_bind_addr_; mme_addr = mme_addr_; - pthread_mutex_init(&mutex, NULL); - + pthread_mutex_init(&mutex, NULL); + pool = byte_buffer_pool::get_instance(); // Set up sink socket @@ -106,11 +105,11 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_ void gtpu::stop() { - + if(enable_mbsfn){ mchthread.stop(); } - + if (run_enable) { run_enable = false; // Wait thread to exit gracefully otherwise might leave a mutex locked @@ -124,7 +123,7 @@ void gtpu::stop() } wait_thread_finish(); } - + if (snk_fd) { close(snk_fd); } @@ -148,7 +147,7 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* pdu) servaddr.sin_addr.s_addr = htonl(rnti_bearers[rnti].spgw_addrs[lcid]); servaddr.sin_port = htons(GTPU_PORT); - gtpu_write_header(&header, pdu); + gtpu_write_header(&header, pdu, gtpu_log); if (sendto(snk_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))<0) { perror("sendto"); } @@ -230,7 +229,7 @@ void gtpu::run_thread() pdu->N_bytes = (uint32_t) n; gtpu_header_t header; - gtpu_read_header(pdu, &header); + gtpu_read_header(pdu, &header,gtpu_log); uint16_t rnti = 0; uint16_t lcid = 0; @@ -265,69 +264,6 @@ void gtpu::run_thread() running = false; } -/**************************************************************************** -* Header pack/unpack helper functions -* Ref: 3GPP TS 29.281 v10.1.0 Section 5 -***************************************************************************/ - -bool gtpu::gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu) -{ - if(header->flags != 0x30) { - gtpu_log->error("gtpu_write_header - Unhandled header flags: 0x%x\n", header->flags); - return false; - } - if(header->message_type != 0xFF) { - gtpu_log->error("gtpu_write_header - Unhandled message type: 0x%x\n", header->message_type); - return false; - } - if(pdu->get_headroom() < GTPU_HEADER_LEN) { - gtpu_log->error("gtpu_write_header - No room in PDU for header\n"); - return false; - } - - pdu->msg -= GTPU_HEADER_LEN; - pdu->N_bytes += GTPU_HEADER_LEN; - - uint8_t *ptr = pdu->msg; - - *ptr = header->flags; - ptr++; - *ptr = header->message_type; - ptr++; - uint16_to_uint8(header->length, ptr); - ptr += 2; - uint32_to_uint8(header->teid, ptr); - - return true; -} - -bool gtpu::gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header) -{ - uint8_t *ptr = pdu->msg; - - pdu->msg += GTPU_HEADER_LEN; - pdu->N_bytes -= GTPU_HEADER_LEN; - - header->flags = *ptr; - ptr++; - header->message_type = *ptr; - ptr++; - uint8_to_uint16(ptr, &header->length); - ptr += 2; - uint8_to_uint32(ptr, &header->teid); - - if(header->flags != 0x30) { - gtpu_log->error("gtpu_read_header - Unhandled header flags: 0x%x\n", header->flags); - return false; - } - if(header->message_type != 0xFF) { - gtpu_log->error("gtpu_read_header - Unhandled message type: 0x%x\n", header->message_type); - return false; - } - - return true; -} - /**************************************************************************** * TEID to RNIT/LCID helper functions ***************************************************************************/ @@ -429,7 +365,7 @@ void gtpu::mch_thread::run_thread() pdu->N_bytes = (uint32_t) n; gtpu_header_t header; - gtpu_read_header(pdu, &header); + gtpu_read_header(pdu, &header, gtpu_log); pdcp->write_sdu(SRSLTE_MRNTI, lcid, pdu); do { From dc3cc43e0213cf2ee19f80499d65812bf4f4d51c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 3 Jul 2018 14:45:50 +0100 Subject: [PATCH 08/28] Changing SPGW to pass log to lib function. --- srsepc/src/spgw/spgw.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 4877ddeb9..20311cc16 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -369,7 +369,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) header.teid = enb_fteid.teid; //Write header into packet - if(!srslte::gtpu_write_header(&header, msg)) + if(!srslte::gtpu_write_header(&header, msg, m_spgw_log)) { m_spgw_log->console("Error writing GTP-U header on PDU\n"); } @@ -395,7 +395,7 @@ spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) { //m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); srslte::gtpu_header_t header; - srslte::gtpu_read_header(msg, &header); + srslte::gtpu_read_header(msg, &header, m_spgw_log); //m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); int n = write(m_sgi_if, msg->msg, msg->N_bytes); From ced47af7bacd894d39b488a28d42ba2580258e4b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 3 Jul 2018 16:58:30 +0100 Subject: [PATCH 09/28] Chenging the MBMS-Gw to pass the log to the gtpu_write_header. --- srsepc/src/mbms-gw/mbms-gw.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index 3031fc1c8..e29b6629f 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -308,7 +308,7 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) } //Write GTP-U header into packet - if(!srslte::gtpu_write_header(&header, msg)) + if(!srslte::gtpu_write_header(&header, msg, m_mbms_gw_log)) { m_mbms_gw_log->console("Error writing GTP-U header on PDU\n"); } From f7a791866d54c9f23be3cda9f91c3cfa7889ee71 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 4 Jul 2018 15:23:05 +0200 Subject: [PATCH 10/28] turn sanity check in RLC_AM into info rather then error --- lib/src/upper/rlc_am.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 40d24e8a2..8a5bfde3e 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -1111,7 +1111,7 @@ void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) // sanity check if (status.nacks[j].so_start >= it->second.buf->N_bytes) { // print error but try to send original PDU again - log->error("SO_start is larger than original PDU (%d >= %d)\n", + log->info("SO_start is larger than original PDU (%d >= %d)\n", status.nacks[j].so_start, it->second.buf->N_bytes); status.nacks[j].so_start = 0; From 9b9a56e54361972cc90d2cce7039085e2e168724 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 4 Jul 2018 15:35:42 +0200 Subject: [PATCH 11/28] fix printf in RLC_AM --- lib/src/upper/rlc_am.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 8a5bfde3e..b1f634a0c 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -1213,7 +1213,7 @@ void rlc_am::reassemble_rx_sdus() #endif } } else { - log->error("Cannot read %d bytes from rx_window. vr_r=%d, tailroom=%d bytes\n", len, rx_window[vr_r].buf->get_tailroom()); + log->error("Cannot read %d bytes from rx_window. vr_r=%d, tailroom=%d bytes\n", len, vr_r, rx_window[vr_r].buf->get_tailroom()); pool->deallocate(rx_sdu); goto exit; } @@ -1289,7 +1289,6 @@ void rlc_am::debug_state() "vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d\n", rrc->get_rb_name(lcid).c_str(), vt_a, vt_ms, vt_s, poll_sn, vr_r, vr_mr, vr_x, vr_ms, vr_h); - } void rlc_am::print_rx_segments() From 1248a4224a92e93175ccbe61a73494d6ee25c4ca Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 4 Jul 2018 19:28:56 +0200 Subject: [PATCH 12/28] Initialize nof_coworkers --- srsue/src/phy/phy.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 3e2454f12..3725a0254 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -52,7 +52,7 @@ namespace srsue { phy::phy() : workers_pool(MAX_WORKERS), workers(MAX_WORKERS), - workers_common(phch_recv::MUTEX_X_WORKER*MAX_WORKERS) + workers_common(phch_recv::MUTEX_X_WORKER*MAX_WORKERS),nof_coworkers(0) { } @@ -169,6 +169,7 @@ void phy::run_thread() { } for (uint32_t i=0;i Date: Wed, 4 Jul 2018 21:43:37 +0200 Subject: [PATCH 13/28] add signal handler to benchmark_radio and fix runtime --- lib/src/radio/test/benchmark_radio.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/src/radio/test/benchmark_radio.cc b/lib/src/radio/test/benchmark_radio.cc index d9279a351..db3371cd7 100644 --- a/lib/src/radio/test/benchmark_radio.cc +++ b/lib/src/radio/test/benchmark_radio.cc @@ -25,6 +25,7 @@ */ #include +#include #include "srslte/srslte.h" #include "srslte/radio/radio_multi.h" @@ -85,18 +86,31 @@ void parse_args(int argc, char **argv) { } } +bool go_exit = false; +void sig_int_handler(int signo) +{ + printf("SIGINT received. Exiting...\n"); + if (signo == SIGINT) { + go_exit = true; + } else if (signo == SIGSEGV) { + exit(1); + } +} + int main(int argc, char **argv) { int ret = SRSLTE_ERROR; srslte::radio_multi *radio_h = NULL; srslte_timestamp_t ts_rx = {}, ts_tx = {}; + signal(SIGINT, sig_int_handler); + /* Parse args */ parse_args(argc, argv); uint32_t nof_samples = (uint32_t) (duration * srate); uint32_t frame_size = (uint32_t) (srate / 1000.0); /* 1 ms at srate */ - uint32_t nof_frames = (uint32_t) ceil(nof_samples / frame_size); + uint32_t nof_frames = duration * 1e3; radio_h = new radio_multi(); if (!radio_h) { @@ -155,6 +169,8 @@ int main(int argc, char **argv) } nof_samples -= frame_size; + + if (go_exit) break; } printf("Finished streaming ...\n"); From fae5531bccc82f37dbb51f67314c3fc98576b16d Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 10:56:32 +0200 Subject: [PATCH 14/28] Correction to commit 2a4a84a578115967a569b8993bef65aef72a3dc7. We don't check for tailroom but for read space --- lib/src/upper/rlc_am.cc | 4 ++-- srsue/src/phy/phy.cc | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index b1f634a0c..a38424328 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -1193,7 +1193,7 @@ void rlc_am::reassemble_rx_sdus() } if (rx_sdu->get_tailroom() >= len) { - if (rx_window[vr_r].buf->get_tailroom() >= len) { + if ((rx_window[vr_r].buf->msg - rx_window[vr_r].buf->buffer) + len < SRSLTE_MAX_BUFFER_SIZE_BYTES) { memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_r].buf->msg, len); rx_sdu->N_bytes += len; rx_window[vr_r].buf->msg += len; @@ -1213,7 +1213,7 @@ void rlc_am::reassemble_rx_sdus() #endif } } else { - log->error("Cannot read %d bytes from rx_window. vr_r=%d, tailroom=%d bytes\n", len, vr_r, rx_window[vr_r].buf->get_tailroom()); + log->error("Cannot read %d bytes from rx_window. vr_r=%d, msg-buffer=%d bytes\n", len, vr_r, (rx_window[vr_r].buf->msg - rx_window[vr_r].buf->buffer)); pool->deallocate(rx_sdu); goto exit; } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 3725a0254..47354156d 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -169,7 +169,6 @@ void phy::run_thread() { } for (uint32_t i=0;i Date: Thu, 5 Jul 2018 11:00:19 +0200 Subject: [PATCH 15/28] Changes on srsENB mutexing logic to fix general race condition and deadlock issues (#229) * fixed some issues with the UL scheduling * Hack to fix UL scheduler * minor fix * Cleaned up code and fixed issue with the update_allocation function * fixed the console printing in the enb * log/console fix * fixed the log print * added a normalization factor * RLC: entity uses dynamic instances. Simplified stop/reset/reestablish procedure. Added non-blocking interface * Limit decimals in metrics stdout * Changed mutexes to rwlock in RLC/RRC/MAC/PDCP to fix race conditions when removing users * Fix deadlock bug for MIMO * Remove headers * Fix missing unlock causing overflows * Do not decrease CQI when PUCCH (this is a temporal fix, requires to reduce the maximum MCS) * Fix mutex unlock in worker * Configurable RLC tx buffer. Default to 512 for enodeb * Check NULL SDU in write_sdu() * Protect RLC objects and tx_queue from being destroyed while using it * Remove superfluous code * Disable SIB logging * Fix block_queue for enb --- lib/include/srslte/common/block_queue.h | 141 +++-- .../srslte/interfaces/enb_interfaces.h | 3 +- lib/include/srslte/upper/rlc.h | 5 +- lib/include/srslte/upper/rlc_am.h | 6 +- lib/include/srslte/upper/rlc_common.h | 3 +- lib/include/srslte/upper/rlc_entity.h | 11 +- lib/include/srslte/upper/rlc_tm.h | 7 +- lib/include/srslte/upper/rlc_tx_queue.h | 7 +- lib/include/srslte/upper/rlc_um.h | 6 +- lib/src/upper/rlc.cc | 30 +- lib/src/upper/rlc_am.cc | 60 +- lib/src/upper/rlc_entity.cc | 76 ++- lib/src/upper/rlc_tm.cc | 52 +- lib/src/upper/rlc_um.cc | 61 +- lib/test/upper/rlc_am_test.cc | 2 +- srsenb/hdr/mac/mac.h | 3 +- srsenb/hdr/mac/scheduler.h | 18 +- srsenb/hdr/mac/scheduler_ue.h | 20 +- srsenb/hdr/upper/pdcp.h | 8 +- srsenb/hdr/upper/rlc.h | 11 +- srsenb/hdr/upper/rrc.h | 2 +- srsenb/src/mac/mac.cc | 533 ++++++++++-------- srsenb/src/mac/scheduler.cc | 143 ++--- srsenb/src/mac/scheduler_ue.cc | 342 ++++++++--- srsenb/src/mac/ue.cc | 6 +- srsenb/src/metrics_stdout.cc | 36 +- srsenb/src/phy/phch_worker.cc | 13 +- srsenb/src/upper/pdcp.cc | 33 +- srsenb/src/upper/rlc.cc | 69 ++- srsenb/src/upper/rrc.cc | 21 +- 30 files changed, 1077 insertions(+), 651 deletions(-) diff --git a/lib/include/srslte/common/block_queue.h b/lib/include/srslte/common/block_queue.h index 3df22b40d..63b0e4177 100644 --- a/lib/include/srslte/common/block_queue.h +++ b/lib/include/srslte/common/block_queue.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include namespace srslte { @@ -63,6 +65,28 @@ public: pthread_cond_init(&cv_full, NULL); this->capacity = capacity; mutexed_callback = NULL; + enable = true; + num_threads = 0; + } + ~block_queue() { + // Unlock threads waiting at push or pop + pthread_mutex_lock(&mutex); + enable = false; + pthread_cond_signal(&cv_full); + pthread_cond_signal(&cv_empty); + pthread_mutex_unlock(&mutex); + + // Wait threads blocked in push/pop to exit + while(num_threads>0) { + usleep(100); + } + + // Wait them to exit and destroy cv and mutex + pthread_mutex_lock(&mutex); + pthread_cond_destroy(&cv_full); + pthread_cond_destroy(&cv_empty); + pthread_mutex_unlock(&mutex); + pthread_mutex_destroy(&mutex); } void set_mutexed_itf(call_mutexed_itf *itf) { mutexed_callback = itf; @@ -70,26 +94,6 @@ public: void resize(int new_capacity) { capacity = new_capacity; } - bool push_(const myobj& value, bool block) { - pthread_mutex_lock(&mutex); - if (capacity > 0) { - if (block) { - while(q.size() > (uint32_t) capacity) { - pthread_cond_wait(&cv_full, &mutex); - } - } else { - pthread_mutex_unlock(&mutex); - return false; - } - } - q.push(value); - if (mutexed_callback) { - mutexed_callback->pushing(value); - } - pthread_cond_signal(&cv_empty); - pthread_mutex_unlock(&mutex); - return true; - } void push(const myobj& value) { push_(value, true); @@ -99,36 +103,14 @@ public: return push_(value, false); } - bool try_pop(myobj *value) { - pthread_mutex_lock(&mutex); - if (q.empty()) { - pthread_mutex_unlock(&mutex); - return false; - } - if (value) { - *value = q.front(); - q.pop(); - } - if (mutexed_callback) { - mutexed_callback->popping(*value); - } - pthread_cond_signal(&cv_full); - pthread_mutex_unlock(&mutex); - return true; + bool try_pop(myobj *value) { + return pop_(value, false); } myobj wait_pop() { // blocking pop - pthread_mutex_lock(&mutex); - while(q.empty()) { - pthread_cond_wait(&cv_empty, &mutex); - } - myobj value = q.front(); - q.pop(); - if (mutexed_callback) { - mutexed_callback->popping(value); - } - pthread_cond_signal(&cv_full); - pthread_mutex_unlock(&mutex); + myobj value; + bzero(&value, sizeof(myobj)); + pop_(&value, true); return value; } @@ -153,12 +135,77 @@ public: } private: + + bool pop_(myobj *value, bool block) { + if (!enable) { + return false; + } + pthread_mutex_lock(&mutex); + num_threads++; + bool ret = false; + if (q.empty() && !block) { + goto exit; + } + while (q.empty() && enable) { + pthread_cond_wait(&cv_empty, &mutex); + } + if (!enable) { + goto exit; + } + if (value) { + *value = q.front(); + q.pop(); + } + ret = true; + if (mutexed_callback) { + mutexed_callback->popping(*value); + } + pthread_cond_signal(&cv_full); + exit: + num_threads--; + pthread_mutex_unlock(&mutex); + return ret; + } + + bool push_(const myobj& value, bool block) { + if (!enable) { + return false; + } + pthread_mutex_lock(&mutex); + num_threads++; + bool ret = false; + if (capacity > 0) { + if (block) { + while(q.size() >= (uint32_t) capacity && enable) { + pthread_cond_wait(&cv_full, &mutex); + } + if (!enable) { + goto exit; + } + } else if (q.size() >= (uint32_t) capacity) { + goto exit; + } + } + q.push(value); + ret = true; + if (mutexed_callback) { + mutexed_callback->pushing(value); + } + pthread_cond_signal(&cv_empty); + exit: + num_threads--; + pthread_mutex_unlock(&mutex); + return ret; + } + std::queue q; pthread_mutex_t mutex; pthread_cond_t cv_empty; pthread_cond_t cv_full; call_mutexed_itf *mutexed_callback; int capacity; + bool enable; + uint32_t num_threads; }; } diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 550e6e3ea..643336bfa 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -173,8 +173,7 @@ public: class rlc_interface_rrc { public: - virtual void reset(uint16_t rnti) = 0; - virtual void clear_buffer(uint16_t rnti) = 0; + virtual void clear_buffer(uint16_t rnti) = 0; virtual void add_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid) = 0; diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 888dfa4f1..8d6eb2fd5 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -56,13 +56,15 @@ public: srsue::ue_interface *ue_, log *rlc_log_, mac_interface_timers *mac_timers_, - uint32_t lcid_); + uint32_t lcid_, + int buffer_size = -1); // -1 to use default buffer sizes void stop(); void get_metrics(rlc_metrics_t &m); // PDCP interface void write_sdu(uint32_t lcid, byte_buffer_t *sdu); + void write_sdu_nb(uint32_t lcid, byte_buffer_t *sdu); void write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu); bool rb_is_um(uint32_t lcid); @@ -99,6 +101,7 @@ private: srslte::rlc_entity rlc_array[SRSLTE_N_RADIO_BEARERS]; srslte::rlc_um rlc_array_mrb[SRSLTE_N_MCH_LCIDS]; uint32_t default_lcid; + int buffer_size; long ul_tput_bytes[SRSLTE_N_RADIO_BEARERS]; long dl_tput_bytes[SRSLTE_N_RADIO_BEARERS]; diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index 3a8c2cc16..cfaee6c5c 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -70,7 +70,7 @@ class rlc_am :public rlc_common { public: - rlc_am(); + rlc_am(uint32_t queue_len = 16); ~rlc_am(); void init(log *rlc_entity_log_, uint32_t lcid_, @@ -78,9 +78,9 @@ public: srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); - void reset(); void reestablish(); void stop(); + void empty_queue(); rlc_mode_t get_mode(); @@ -88,6 +88,7 @@ public: // PDCP interface void write_sdu(byte_buffer_t *sdu); + void write_sdu_nb(byte_buffer_t *sdu); // MAC interface uint32_t get_buffer_state(); @@ -122,6 +123,7 @@ private: // Mutexes pthread_mutex_t mutex; + bool tx_enabled; bool poll_received; bool do_status; rlc_status_pdu_t status; diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 9be390d31..bfc21f711 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -151,13 +151,13 @@ struct rlc_status_pdu_t{ class rlc_common { public: + virtual ~rlc_common() {} virtual void init(srslte::log *rlc_entity_log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, srslte::mac_interface_timers *mac_timers_) = 0; virtual void configure(srslte_rlc_config_t cnfg) = 0; - virtual void reset() = 0; virtual void stop() = 0; virtual void empty_queue() = 0; @@ -166,6 +166,7 @@ public: // PDCP interface virtual void write_sdu(byte_buffer_t *sdu) = 0; + virtual void write_sdu_nb(byte_buffer_t *sdu) = 0; // MAC interface virtual uint32_t get_buffer_state() = 0; diff --git a/lib/include/srslte/upper/rlc_entity.h b/lib/include/srslte/upper/rlc_entity.h index eca470709..894572c14 100644 --- a/lib/include/srslte/upper/rlc_entity.h +++ b/lib/include/srslte/upper/rlc_entity.h @@ -52,10 +52,10 @@ public: uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers_); + mac_interface_timers *mac_timers_, + int buffer_size = -1); // use -1 for default buffer sizes void configure(srslte_rlc_config_t cnfg); - void reset(); void reestablish(); void stop(); void empty_queue(); @@ -66,6 +66,7 @@ public: // PDCP interface void write_sdu(byte_buffer_t *sdu); + void write_sdu_nb(byte_buffer_t *sdu); // MAC interface uint32_t get_buffer_state(); @@ -75,10 +76,8 @@ public: private: - rlc_tm tm; - rlc_um um; - rlc_am am; - + rlc_mode_t mode; + uint32_t lcid; rlc_common *rlc; }; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index ecb79e653..774011292 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -40,14 +40,14 @@ class rlc_tm :public rlc_common { public: - rlc_tm(); + rlc_tm(uint32_t queue_len = 16); + ~rlc_tm(); void init(log *rlc_entity_log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); - void reset(); void stop(); void empty_queue(); @@ -56,6 +56,7 @@ public: // PDCP interface void write_sdu(byte_buffer_t *sdu); + void write_sdu_nb(byte_buffer_t *sdu); // MAC interface uint32_t get_buffer_state(); @@ -71,6 +72,8 @@ private: srsue::pdcp_interface_rlc *pdcp; srsue::rrc_interface_rlc *rrc; + bool tx_enabled; + // Thread-safe queues for MAC messages rlc_tx_queue ul_queue; }; diff --git a/lib/include/srslte/upper/rlc_tx_queue.h b/lib/include/srslte/upper/rlc_tx_queue.h index 08edae0fe..afabcd89e 100644 --- a/lib/include/srslte/upper/rlc_tx_queue.h +++ b/lib/include/srslte/upper/rlc_tx_queue.h @@ -44,7 +44,7 @@ namespace srslte { class rlc_tx_queue : public block_queue::call_mutexed_itf { public: - rlc_tx_queue(uint32_t capacity = 128) : queue((int) capacity) { + rlc_tx_queue(int capacity = 128) : queue(capacity) { unread_bytes = 0; queue.set_mutexed_itf(this); } @@ -64,6 +64,11 @@ public: queue.push(msg); } + bool try_write(byte_buffer_t *msg) + { + return queue.try_push(msg); + } + void read(byte_buffer_t **msg) { byte_buffer_t *m = queue.wait_pop(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 0cd4b8c95..864edaded 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -49,8 +49,7 @@ class rlc_um ,public rlc_common { public: - rlc_um(); - + rlc_um(uint32_t queue_len = 32); ~rlc_um(); void init(log *rlc_entity_log_, uint32_t lcid_, @@ -58,7 +57,6 @@ public: srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers_); void configure(srslte_rlc_config_t cnfg); - void reset(); void stop(); void empty_queue(); bool is_mrb(); @@ -68,6 +66,7 @@ public: // PDCP interface void write_sdu(byte_buffer_t *sdu); + void write_sdu_nb(byte_buffer_t *sdu); // MAC interface uint32_t get_buffer_state(); @@ -131,6 +130,7 @@ private: srslte::timers::timer *reordering_timer; uint32_t reordering_timer_id; + bool tx_enabled; bool pdu_lost; int build_data_pdu(uint8_t *payload, uint32_t nof_bytes); diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 5b26add1b..7fa514e08 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -51,7 +51,8 @@ void rlc::init(srsue::pdcp_interface_rlc *pdcp_, srsue::ue_interface *ue_, log *rlc_log_, mac_interface_timers *mac_timers_, - uint32_t lcid_) + uint32_t lcid_, + int buffer_size_) { pdcp = pdcp_; rrc = rrc_; @@ -59,11 +60,12 @@ void rlc::init(srsue::pdcp_interface_rlc *pdcp_, rlc_log = rlc_log_; mac_timers = mac_timers_; default_lcid = lcid_; + buffer_size = buffer_size_; gettimeofday(&metrics_time[1], NULL); reset_metrics(); - rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers); // SRB0 + rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers, buffer_size); // SRB0 } void rlc::reset_metrics() @@ -75,8 +77,9 @@ void rlc::reset_metrics() void rlc::stop() { for(uint32_t i=0; ierror("Cannot add RLC entity - invalid mode\n"); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index a38424328..51aeb6a34 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -36,7 +36,7 @@ namespace srslte { -rlc_am::rlc_am() : tx_sdu_queue(16) +rlc_am::rlc_am(uint32_t queue_len) : tx_sdu_queue(queue_len) { log = NULL; pdcp = NULL; @@ -68,19 +68,13 @@ rlc_am::rlc_am() : tx_sdu_queue(16) do_status = false; } +// Warning: must call stop() to properly deallocate all buffers rlc_am::~rlc_am() { - // reset RLC and dealloc SDUs - stop(); - - if(rx_sdu) { - pool->deallocate(rx_sdu); - } - - if(tx_sdu) { - pool->deallocate(tx_sdu); - } + pthread_mutex_destroy(&mutex); + pool = NULL; } + void rlc_am::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, @@ -91,6 +85,7 @@ void rlc_am::init(srslte::log *log_, lcid = lcid_; pdcp = pdcp_; rrc = rrc_; + tx_enabled = true; } void rlc_am::configure(srslte_rlc_config_t cfg_) @@ -106,21 +101,16 @@ void rlc_am::configure(srslte_rlc_config_t cfg_) void rlc_am::empty_queue() { // Drop all messages in TX SDU queue byte_buffer_t *buf; - while(tx_sdu_queue.size() > 0) { - tx_sdu_queue.read(&buf); + while(tx_sdu_queue.try_read(&buf)) { pool->deallocate(buf); } } void rlc_am::stop() { - reset(); - pthread_mutex_destroy(&mutex); -} - -void rlc_am::reset() -{ - // Empty tx_sdu_queue before locking the mutex + // Empty tx_sdu_queue before locking the mutex + tx_enabled = false; + usleep(100); empty_queue(); pthread_mutex_lock(&mutex); @@ -198,8 +188,34 @@ uint32_t rlc_am::get_bearer() void rlc_am::write_sdu(byte_buffer_t *sdu) { - tx_sdu_queue.write(sdu); - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + tx_sdu_queue.write(sdu); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } +} + +void rlc_am::write_sdu_nb(byte_buffer_t *sdu) +{ + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + if (tx_sdu_queue.try_write(sdu)) { + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + } else { + log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + pool->deallocate(sdu); + } + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } } /**************************************************************************** diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index 81692889c..9ac526868 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -33,34 +33,49 @@ rlc_entity::rlc_entity() { } -void rlc_entity::init(rlc_mode_t mode, +void rlc_entity::init(rlc_mode_t mode_, log *rlc_entity_log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers_) + mac_interface_timers *mac_timers_, + int buffer_size) { - tm.reset(); - um.reset(); - am.reset(); - - switch(mode) - { - case RLC_MODE_TM: - rlc = &tm; - break; - case RLC_MODE_UM: - rlc = &um; - break; - case RLC_MODE_AM: - rlc = &am; - break; - default: - rlc_entity_log_->error("Invalid RLC mode - defaulting to TM\n"); - rlc = &tm; - break; - } + if (buffer_size <= 0) { + buffer_size = 16; + } + // Create the RLC instance the first time init() is called. + // If called to reestablished, the entity is stopped but not destroyed + // Next call to init() must use same mode + if (rlc == NULL) { + switch(mode_) + { + case RLC_MODE_TM: + rlc = new rlc_tm((uint32_t) buffer_size); + break; + case RLC_MODE_UM: + rlc = new rlc_um((uint32_t) buffer_size); + break; + case RLC_MODE_AM: + rlc = new rlc_am((uint32_t) buffer_size); + break; + default: + rlc_entity_log_->error("Invalid RLC mode - defaulting to TM\n"); + rlc = new rlc_tm((uint32_t) buffer_size); + break; + } + lcid = lcid_; + mode = mode_; + } else { + if (lcid != lcid_) { + rlc_entity_log_->warning("Reestablishing RLC instance. LCID changed from %d to %d\n", lcid, lcid_); + lcid = lcid_; + } + if (mode != mode_) { + rlc_entity_log_->console("Error reestablishing RLC instance. Mode changed from %d to %d. \n", mode, mode_); + } + } rlc->init(rlc_entity_log_, lcid_, pdcp_, rrc_, mac_timers_); } @@ -70,19 +85,16 @@ void rlc_entity::configure(srslte_rlc_config_t cnfg) rlc->configure(cnfg); } +// Reestablishment stops the entity but does not destroy it. Mode will not change void rlc_entity::reestablish() { - rlc->reset(); -} - -void rlc_entity::reset() -{ - rlc->reset(); - rlc = NULL; + rlc->stop(); } +// A call to stop() stops the entity and clears deletes the instance. Next time this entity can be used for other mode. void rlc_entity::stop() { rlc->stop(); + delete rlc; rlc = NULL; } @@ -119,6 +131,12 @@ void rlc_entity::write_sdu(byte_buffer_t *sdu) rlc->write_sdu(sdu); } +void rlc_entity::write_sdu_nb(byte_buffer_t *sdu) +{ + if(rlc) + rlc->write_sdu_nb(sdu); +} + // MAC interface uint32_t rlc_entity::get_buffer_state() { diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 0dd16bf4d..9c367dada 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -29,7 +29,7 @@ namespace srslte { -rlc_tm::rlc_tm() : ul_queue(16) +rlc_tm::rlc_tm(uint32_t queue_len) : ul_queue(queue_len) { log = NULL; pdcp = NULL; @@ -38,6 +38,11 @@ rlc_tm::rlc_tm() : ul_queue(16) pool = byte_buffer_pool::get_instance(); } +// Warning: must call stop() to properly deallocate all buffers +rlc_tm::~rlc_tm() { + pool = NULL; +} + void rlc_tm::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, @@ -48,6 +53,7 @@ void rlc_tm::init(srslte::log *log_, lcid = lcid_; pdcp = pdcp_; rrc = rrc_; + tx_enabled = true; } void rlc_tm::configure(srslte_rlc_config_t cnfg) @@ -64,14 +70,10 @@ void rlc_tm::empty_queue() } } -void rlc_tm::reset() -{ - empty_queue(); -} - void rlc_tm::stop() { - reset(); + tx_enabled = false; + empty_queue(); } rlc_mode_t rlc_tm::get_mode() @@ -87,11 +89,37 @@ uint32_t rlc_tm::get_bearer() // PDCP interface void rlc_tm::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, before: queue size=%d, bytes=%d", - rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); - ul_queue.write(sdu); - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, after: queue size=%d, bytes=%d", - rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + ul_queue.write(sdu); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", + rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } +} + +void rlc_tm::write_sdu_nb(byte_buffer_t *sdu) +{ + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + if (ul_queue.try_write(sdu)) { + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", + rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); + } else { + log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d", + rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); + pool->deallocate(sdu); + } + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } } // MAC interface diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 042f4d059..190380675 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -33,7 +33,7 @@ namespace srslte { -rlc_um::rlc_um() : tx_sdu_queue(32) +rlc_um::rlc_um(uint32_t queue_len) : tx_sdu_queue(queue_len) { log = NULL; pdcp = NULL; @@ -62,10 +62,13 @@ rlc_um::rlc_um() : tx_sdu_queue(32) pdu_lost = false; } +// Warning: must call stop() to properly deallocate all buffers rlc_um::~rlc_um() { - stop(); + pthread_mutex_destroy(&mutex); + pool = NULL; } + void rlc_um::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, @@ -79,6 +82,7 @@ void rlc_um::init(srslte::log *log_, mac_timers = mac_timers_; reordering_timer_id = mac_timers->timer_get_unique_id(); reordering_timer = mac_timers->timer_get(reordering_timer_id); + tx_enabled = true; } void rlc_um::configure(srslte_rlc_config_t cnfg_) @@ -115,8 +119,7 @@ void rlc_um::configure(srslte_rlc_config_t cnfg_) void rlc_um::empty_queue() { // Drop all messages in TX SDU queue byte_buffer_t *buf; - while(tx_sdu_queue.size() > 0) { - tx_sdu_queue.read(&buf); + while(tx_sdu_queue.try_read(&buf)) { pool->deallocate(buf); } } @@ -128,16 +131,8 @@ bool rlc_um::is_mrb() void rlc_um::stop() { - reset(); - if (mac_timers && reordering_timer) { - mac_timers->timer_release_id(reordering_timer_id); - reordering_timer = NULL; - } -} - -void rlc_um::reset() -{ - // Empty tx_sdu_queue before locking the mutex + // Empty tx_sdu_queue before locking the mutex + tx_enabled = false; empty_queue(); pthread_mutex_lock(&mutex); @@ -159,7 +154,7 @@ void rlc_um::reset() if(reordering_timer) { reordering_timer->stop(); } - + // Drop all messages in RX window std::map::iterator it; for(it = rx_window.begin(); it != rx_window.end(); it++) { @@ -167,6 +162,11 @@ void rlc_um::reset() } rx_window.clear(); pthread_mutex_unlock(&mutex); + + if (mac_timers && reordering_timer) { + mac_timers->timer_release_id(reordering_timer_id); + reordering_timer = NULL; + } } rlc_mode_t rlc_um::get_mode() @@ -182,11 +182,36 @@ uint32_t rlc_um::get_bearer() /**************************************************************************** * PDCP interface ***************************************************************************/ - void rlc_um::write_sdu(byte_buffer_t *sdu) { - tx_sdu_queue.write(sdu); - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + tx_sdu_queue.write(sdu); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } +} + +void rlc_um::write_sdu_nb(byte_buffer_t *sdu) +{ + if (!tx_enabled) { + byte_buffer_pool::get_instance()->deallocate(sdu); + return; + } + if (sdu) { + if (tx_sdu_queue.try_write(sdu)) { + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + } else { + log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + pool->deallocate(sdu); + } + } else { + log->warning("NULL SDU pointer in write_sdu()\n"); + } } /**************************************************************************** diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 41057fbd5..ef04062cc 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -1408,7 +1408,7 @@ void reset_test() pdu_bufs.N_bytes = len; // reset RLC1 - rlc1.reset(); + rlc1.stop(); // read another PDU segment from RLC1 len = rlc1.read_pdu(pdu_bufs.msg, 4); diff --git a/srsenb/hdr/mac/mac.h b/srsenb/hdr/mac/mac.h index 61aa033fd..ed7726803 100644 --- a/srsenb/hdr/mac/mac.h +++ b/srsenb/hdr/mac/mac.h @@ -124,7 +124,8 @@ private: static const int MAC_PDU_THREAD_PRIO = 60; - + // We use a rwlock in MAC to allow multiple workers to access MAC simultaneously. No conflicts will happen since access for different TTIs + pthread_rwlock_t rwlock; // Interaction with PHY phy_interface_mac *phy_h; diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index 48445a0e1..0c69bcbef 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -36,8 +36,15 @@ #include namespace srsenb { - - + + +/* Caution: User addition (ue_cfg) and removal (ue_rem) are not thread-safe + * Rest of operations are thread-safe + * + * The subclass sched_ue is thread-safe so that access to shared variables like buffer states + * from scheduler thread and other threads is protected for each individual user. + */ + class sched : public sched_interface { @@ -89,7 +96,7 @@ public: void set_sched_cfg(sched_args_t *sched_cfg); int reset(); - int ue_cfg(uint16_t rnti, ue_cfg_t *ue_cfg); + int ue_cfg(uint16_t rnti, ue_cfg_t *ue_cfg); int ue_rem(uint16_t rnti); bool ue_exists(uint16_t rnti); @@ -216,10 +223,7 @@ private: uint32_t current_cfi; bool configured; - - pthread_mutex_t mutex, mutex2; - - + }; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index aafad89a6..84afd8c7f 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -35,6 +35,12 @@ namespace srsenb { + +/** This class is designed to be thread-safe because it is called from workers through scheduler thread and from + * higher layers and mac threads. + * + * 1 mutex is created for every user and only access to same user variables are mutexed + */ class sched_ue { public: @@ -56,6 +62,7 @@ public: * ************************************************************/ sched_ue(); + ~sched_ue(); void reset(); void phy_config_enabled(uint32_t tti, bool enabled); void set_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg, sched_interface::cell_cfg_t *cell_cfg, @@ -101,6 +108,7 @@ public: uint32_t get_pending_dl_new_data(uint32_t tti); uint32_t get_pending_ul_new_data(uint32_t tti); + uint32_t get_pending_ul_old_data(); uint32_t get_pending_dl_new_data_total(uint32_t tti); dl_harq_proc *get_pending_dl_harq(uint32_t tti); @@ -129,8 +137,6 @@ public: bool get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]); bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce); - uint32_t get_pending_ul_old_data(); - private: typedef struct { @@ -152,11 +158,21 @@ private: static bool bearer_is_ul(ue_bearer_t *lch); static bool bearer_is_dl(ue_bearer_t *lch); + uint32_t get_pending_dl_new_data_unlocked(uint32_t tti); + uint32_t get_pending_ul_old_data_unlocked(); + uint32_t get_pending_ul_new_data_unlocked(uint32_t tti); + + bool needs_cqi_unlocked(uint32_t tti, bool will_send = false); + + int generate_format2a_unlocked(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + bool is_first_dl_tx(); sched_interface::ue_cfg_t cfg; srslte_cell_t cell; srslte::log* log_h; + + pthread_mutex_t mutex; /* Buffer states */ bool sr; diff --git a/srsenb/hdr/upper/pdcp.h b/srsenb/hdr/upper/pdcp.h index c249b856e..9624958e4 100644 --- a/srsenb/hdr/upper/pdcp.h +++ b/srsenb/hdr/upper/pdcp.h @@ -103,9 +103,13 @@ private: user_interface_gtpu gtpu_itf; user_interface_rrc rrc_itf; srslte::pdcp *pdcp; - }; + }; + + void clear_user(user_interface *ue); - std::map users; + std::map users; + + pthread_rwlock_t rwlock; rlc_interface_pdcp *rlc; rrc_interface_pdcp *rrc; diff --git a/srsenb/hdr/upper/rlc.h b/srsenb/hdr/upper/rlc.h index 2b0752cf1..05d4681f1 100644 --- a/srsenb/hdr/upper/rlc.h +++ b/srsenb/hdr/upper/rlc.h @@ -52,7 +52,6 @@ public: void stop(); // rlc_interface_rrc - void reset(uint16_t rnti); void clear_buffer(uint16_t rnti); void add_user(uint16_t rnti); void rem_user(uint16_t rnti); @@ -91,8 +90,14 @@ private: srsenb::rrc_interface_rlc *rrc; srslte::rlc *rlc; srsenb::rlc *parent; - }; - + }; + + void clear_user(user_interface *ue); + + const static int RLC_TX_QUEUE_LEN = 512; + + pthread_rwlock_t rwlock; + std::map users; std::vector mch_services; diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index 69e2b75ce..26a60e971 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -123,7 +123,6 @@ public: bzero(&cqi_sched, sizeof(cqi_sched)); bzero(&cfg, sizeof(cfg)); bzero(&sib2, sizeof(sib2)); - bzero(&user_mutex, sizeof(user_mutex)); bzero(&paging_mutex, sizeof(paging_mutex)); } @@ -350,6 +349,7 @@ private: srslte::byte_buffer_t* pdu; }rrc_pdu; + const static uint32_t LCID_EXIT = 0xffff0000; const static uint32_t LCID_REM_USER = 0xffff0001; const static uint32_t LCID_REL_USER = 0xffff0002; const static uint32_t LCID_RLF_USER = 0xffff0003; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 3b3919061..02b5686a5 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -96,96 +96,112 @@ bool mac::init(mac_args_t *args_, srslte_cell_t *cell_, phy_interface_mac *phy, reset(); - started = true; + pthread_rwlock_init(&rwlock, NULL); + + started = true; } - return started; + return started; } void mac::stop() { + pthread_rwlock_wrlock(&rwlock); + for (uint32_t i=0;i::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { ue *u = iter->second; u->start_pcap(pcap); - } + } } /******************************************************** * - * RLC interface + * RLC interface * *******************************************************/ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { + pthread_rwlock_rdlock(&rwlock); + int ret = -1; if (ue_db.count(rnti)) { if(rnti != SRSLTE_MRNTI){ - return scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue); + ret = scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue); } else { for(uint32_t i = 0; i < mch.num_mtch_sched; i++){ if(lc_id == mch.mtch_sched[i].lcid){ mch.mtch_sched[i].lcid_buffer_size = tx_queue; } } - return 0; + ret = 0; } } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) { + int ret = -1; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { // configure BSR group in UE ue_db[rnti]->set_lcg(lc_id, (uint32_t) cfg->group); - return scheduler.bearer_ue_cfg(rnti, lc_id, cfg); + ret = scheduler.bearer_ue_cfg(rnti, lc_id, cfg); } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) { - if (ue_db.count(rnti)) { - return scheduler.bearer_ue_rem(rnti, lc_id); + pthread_rwlock_rdlock(&rwlock); + int ret = -1; + if (ue_db.count(rnti)) { + ret = scheduler.bearer_ue_rem(rnti, lc_id); } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } + pthread_rwlock_unlock(&rwlock); + return ret; } void mac::phy_config_enabled(uint16_t rnti, bool enabled) @@ -193,58 +209,74 @@ void mac::phy_config_enabled(uint16_t rnti, bool enabled) scheduler.phy_config_enabled(rnti, enabled); } -// Update UE configuration +// Update UE configuration int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) { - if (ue_db.count(rnti)) { - + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { + // Add RNTI to the PHY (pregerate signals) now instead of after PRACH if (!ue_db[rnti]->is_phy_added) { - ue_db[rnti]->is_phy_added = true; + ue_db[rnti]->is_phy_added = true; Info("Registering rnti=0x%x to PHY...\n", rnti); // Register new user in PHY if (phy_h->add_rnti(rnti)) { - Error("Registering new ue rnti=0x%x to PHY\n", rnti); + Error("Registering new ue rnti=0x%x to PHY\n", rnti); } Info("Done registering rnti=0x%x to PHY...\n", rnti); } - - // Update Scheduler configuration + + // Update Scheduler configuration if (scheduler.ue_cfg(rnti, cfg)) { Error("Registering new UE rnti=0x%x to SCHED\n", rnti); - return -1; - } - return 0; + } else { + ret = 0; + } } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } + pthread_rwlock_unlock(&rwlock); + return ret; } // Removes UE from DB int mac::ue_rem(uint16_t rnti) { - if (ue_db.count(rnti)) { + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { scheduler.ue_rem(rnti); phy_h->rem_rnti(rnti); - delete ue_db[rnti]; + ret = 0; + } else { + Error("User rnti=0x%x not found\n", rnti); + } + pthread_rwlock_unlock(&rwlock); + if (ret) { + return ret; + } + pthread_rwlock_wrlock(&rwlock); + if (ue_db.count(rnti)) { + delete ue_db[rnti]; ue_db.erase(rnti); Info("User rnti=0x%x removed from MAC/PHY\n", rnti); - return 0; } else { - Error("User rnti=0x%x not found\n", rnti); - return -1; + Error("User rnti=0x%x already removed\n", rnti); } + pthread_rwlock_unlock(&rwlock); + return 0; } int mac::cell_cfg(sched_interface::cell_cfg_t* cell_cfg) { memcpy(&this->cell_config, cell_cfg, sizeof(sched_interface::cell_cfg_t)); - return scheduler.cell_cfg(cell_cfg); + return scheduler.cell_cfg(cell_cfg); } void mac::get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]) { + pthread_rwlock_rdlock(&rwlock); int cnt=0; for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { ue *u = iter->second; @@ -252,21 +284,23 @@ void mac::get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]) u->metrics_read(&metrics[cnt]); cnt++; } - } + } + pthread_rwlock_unlock(&rwlock); } /******************************************************** * - * PHY interface + * PHY interface * *******************************************************/ void mac::rl_failure(uint16_t rnti) { - if (ue_db.count(rnti)) { - uint32_t nof_fails = ue_db[rnti]->rl_failure(); - if (nof_fails >= (uint32_t) args.link_failure_nof_err && args.link_failure_nof_err > 0) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { + uint32_t nof_fails = ue_db[rnti]->rl_failure(); + if (nof_fails >= (uint32_t) args.link_failure_nof_err && args.link_failure_nof_err > 0) { Info("Detected Uplink failure for rnti=0x%x\n", rnti); rrc_h->rl_failure(rnti); ue_db[rnti]->rl_failure_reset(); @@ -274,141 +308,166 @@ void mac::rl_failure(uint16_t rnti) } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); } void mac::rl_ok(uint16_t rnti) { - if (ue_db.count(rnti)) { - ue_db[rnti]->rl_failure_reset(); + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { + ue_db[rnti]->rl_failure_reset(); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); } int mac::ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) { + pthread_rwlock_rdlock(&rwlock); log_h->step(tti); uint32_t nof_bytes = scheduler.dl_ack_info(tti, rnti, tb_idx, ack); ue_db[rnti]->metrics_tx(ack, nof_bytes); - + if (ack) { if (nof_bytes > 64) { // do not count RLC status messages only - rrc_h->set_activity_user(rnti); + rrc_h->set_activity_user(rnti); log_h->info("DL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); } } - return 0; + pthread_rwlock_unlock(&rwlock); + return 0; } int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc) { log_h->step(tti); - - if (ue_db.count(rnti)) { + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti]->set_tti(tti); - + ue_db[rnti]->metrics_rx(crc, nof_bytes); - + // push the pdu through the queue if received correctly if (crc) { ue_db[rnti]->push_pdu(tti, nof_bytes); - pdu_process_thread.notify(); + pdu_process_thread.notify(); } else { ue_db[rnti]->deallocate_pdu(tti); } - - return scheduler.ul_crc_info(tti, rnti, crc); + + ret = scheduler.ul_crc_info(tti, rnti, crc); } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { log_h->step(tti); + int ret = -1; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { scheduler.dl_ant_info(rnti, dl_ant_info); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) { log_h->step(tti); - - if (ue_db.count(rnti)) { + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { scheduler.dl_ri_info(tti, rnti, ri_value); ue_db[rnti]->metrics_dl_ri(ri_value); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) { log_h->step(tti); - + pthread_rwlock_rdlock(&rwlock); + int ret = -1; if (ue_db.count(rnti)) { scheduler.dl_pmi_info(tti, rnti, pmi_value); ue_db[rnti]->metrics_dl_pmi(pmi_value); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { log_h->step(tti); + int ret = -1; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { scheduler.dl_cqi_info(tti, rnti, cqi_value); ue_db[rnti]->metrics_dl_cqi(cqi_value); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::snr_info(uint32_t tti, uint16_t rnti, float snr) { log_h->step(tti); - - if (ue_db.count(rnti)) { - uint32_t cqi = srslte_cqi_from_snr(snr); + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { + uint32_t cqi = srslte_cqi_from_snr(snr); scheduler.ul_cqi_info(tti, rnti, cqi, 0); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::sr_detected(uint32_t tti, uint16_t rnti) { log_h->step(tti); - - if (ue_db.count(rnti)) { - scheduler.ul_sr_info(tti, rnti); + int ret = -1; + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { + scheduler.ul_sr_info(tti, rnti); + ret = 0; } else { Error("User rnti=0x%x not found\n", rnti); - return -1; } - return 0; + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) { log_h->step(tti); + int ret = -1; + + pthread_rwlock_rdlock(&rwlock); + // Find empty slot for pending rars uint32_t ra_id=0; while(pending_rars[ra_id].temp_crnti && ra_idconfig(last_rnti, cell.nof_prb, &scheduler, rrc_h, rlc_h, log_h); - - // Set PCAP if available + + // Set PCAP if available if (pcap) { ue_db[last_rnti]->start_pcap(pcap); } // Save RA info - pending_rars[ra_id].preamble_idx = preamble_idx; + pending_rars[ra_id].preamble_idx = preamble_idx; pending_rars[ra_id].ta_cmd = 2*time_adv; - pending_rars[ra_id].temp_crnti = last_rnti; - + pending_rars[ra_id].temp_crnti = last_rnti; + // Add new user to the scheduler so that it can RX/TX SRB0 - sched_interface::ue_cfg_t uecfg; + sched_interface::ue_cfg_t uecfg; bzero(&uecfg, sizeof(sched_interface::ue_cfg_t)); - uecfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + uecfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; if (scheduler.ue_cfg(last_rnti, &uecfg)) { // Release pending RAR bzero(&pending_rars[ra_id], sizeof(pending_rar_t)); Error("Registering new user rnti=0x%x to SCHED\n", last_rnti); - return -1; + goto unlock; } - // Register new user in RRC + // Register new user in RRC rrc_h->add_user(last_rnti); - // Trigger scheduler RACH - scheduler.dl_rach_info(tti, ra_id, last_rnti, 7); - - log_h->info("RACH: tti=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n", - tti, preamble_idx, time_adv, last_rnti); - log_h->console("RACH: tti=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n", - tti, preamble_idx, time_adv, last_rnti); - - // Increae RNTI counter + // Trigger scheduler RACH + scheduler.dl_rach_info(tti, ra_id, last_rnti, 7); + + log_h->info("RACH: tti=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n", + tti, preamble_idx, time_adv, last_rnti); + log_h->console("RACH: tti=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n", + tti, preamble_idx, time_adv, last_rnti); + + // Increae RNTI counter last_rnti++; if (last_rnti >= 60000) { - last_rnti = 70; + last_rnti = 70; } - return 0; + ret = 0; + +unlock: + pthread_rwlock_unlock(&rwlock); + return ret; } int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) @@ -468,76 +531,85 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) if (!started) { return 0; } - + if (!dl_sched_res) { - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } - - // Run scheduler with current info - sched_interface::dl_sched_res_t sched_result; + + // Run scheduler with current info + sched_interface::dl_sched_res_t sched_result; bzero(&sched_result, sizeof(sched_interface::dl_sched_res_t)); if (scheduler.dl_sched(tti, &sched_result) < 0) { Error("Running scheduler\n"); return SRSLTE_ERROR; } - - int n = 0; - - // Copy data grants + + int n = 0; + + pthread_rwlock_rdlock(&rwlock); + + // Copy data grants for (uint32_t i=0;isched_grants[n].rnti = rnti; - dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format; - memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); - memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); - - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - dl_sched_res->sched_grants[n].softbuffers[tb] = - ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process, tb); - - if (sched_result.data[i].nof_pdu_elems[tb] > 0) { - /* Get PDU if it's a new transmission */ - dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(tb, - sched_result.data[i].pdu[tb], - sched_result.data[i].nof_pdu_elems[tb], - sched_result.data[i].tbs[tb]); - - if (!dl_sched_res->sched_grants[n].data[tb]) { - Error("Error! PDU was not generated (rnti=0x%04x, tb=%d)\n", rnti, tb); - sched_result.data[i].dci.tb_en[tb] = false; - } - if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[tb], sched_result.data[i].tbs[tb], rnti, true, tti); + if (ue_db.count(rnti)) { + // Copy grant info + dl_sched_res->sched_grants[n].rnti = rnti; + dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format; + memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); + memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); + + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + dl_sched_res->sched_grants[n].softbuffers[tb] = + ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process, tb); + + if (sched_result.data[i].nof_pdu_elems[tb] > 0) { + /* Get PDU if it's a new transmission */ + dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(tb, + sched_result.data[i].pdu[tb], + sched_result.data[i].nof_pdu_elems[tb], + sched_result.data[i].tbs[tb]); + + if (!dl_sched_res->sched_grants[n].data[tb]) { + Error("Error! PDU was not generated (rnti=0x%04x, tb=%d)\n", rnti, tb); + sched_result.data[i].dci.tb_en[tb] = false; + } + + if (pcap) { + pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[tb], sched_result.data[i].tbs[tb], rnti, true, tti); + } + + } else { + /* TB not enabled OR no data to send: set pointers to NULL */ + dl_sched_res->sched_grants[n].data[tb] = NULL; } - - } else { - /* TB not enabled OR no data to send: set pointers to NULL */ - dl_sched_res->sched_grants[n].data[tb] = NULL; } + n++; + } else { + Warning("Invalid DL scheduling result. User 0x%x does not exist\n", rnti); } - n++; } - // Copy RAR grants + // No more uses of shared ue_db beyond here + pthread_rwlock_unlock(&rwlock); + + // Copy RAR grants for (uint32_t i=0;isched_grants[n].rnti = sched_result.rar[i].rarnti; dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.rar[i].dci, sizeof(srslte_ra_dl_dci_t)); - memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); + memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); // Set softbuffer (there are no retx in RAR but a softbuffer is required) dl_sched_res->sched_grants[n].softbuffers[0] = &rar_softbuffer_tx; - // Assemble PDU + // Assemble PDU dl_sched_res->sched_grants[n].data[0] = assemble_rar(sched_result.rar[i].grants, sched_result.rar[i].nof_grants, i, sched_result.rar[i].tbs); - + if (pcap) { pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.rar[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti); } @@ -545,15 +617,15 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) n++; } - // Copy SI and Paging grants + // Copy SI and Paging grants for (uint32_t i=0;isched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI; dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.bc[i].dci, sizeof(srslte_ra_dl_dci_t)); - memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.bc[i].dci_location, sizeof(srslte_dci_location_t)); - - // Set softbuffer + memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.bc[i].dci_location, sizeof(srslte_dci_location_t)); + + // Set softbuffer if (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH) { dl_sched_res->sched_grants[n].softbuffers[0] = &bcch_softbuffer_tx[sched_result.bc[i].index]; dl_sched_res->sched_grants[n].data[0] = assemble_si(sched_result.bc[i].index); @@ -566,20 +638,20 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) dl_sched_res->sched_grants[n].softbuffers[0] = &pcch_softbuffer_tx; dl_sched_res->sched_grants[n].data[0] = pcch_payload_buffer; rlc_h->read_pdu_pcch(pcch_payload_buffer, pcch_payload_buffer_len); - + if (pcap) { pcap->write_dl_pch(dl_sched_res->sched_grants[n].data[0], sched_result.bc[i].tbs, true, tti); } } - + n++; } - - dl_sched_res->nof_grants = n; - - // Number of CCH symbols - dl_sched_res->cfi = sched_result.cfi; - + + dl_sched_res->nof_grants = n; + + // Number of CCH symbols + dl_sched_res->cfi = sched_result.cfi; + return SRSLTE_SUCCESS; } @@ -587,12 +659,12 @@ void mac::build_mch_sched(uint32_t tbs) { int sfs_per_sched_period = mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9; int bytes_per_sf = tbs/8 - 6;// leave 6 bytes for header - + int total_space_avail_bytes = sfs_per_sched_period*bytes_per_sf; - - int total_bytes_to_tx = 0; - - + + int total_bytes_to_tx = 0; + + // calculate total bytes to be scheduled for (uint32_t i = 0; i < mch.num_mtch_sched; i++) { total_bytes_to_tx += mch.mtch_sched[i].lcid_buffer_size; @@ -600,34 +672,34 @@ void mac::build_mch_sched(uint32_t tbs) } int last_mtch_stop = 0; - + if(total_bytes_to_tx >= total_space_avail_bytes){ for(uint32_t i = 0; i < mch.num_mtch_sched;i++){ double ratio = mch.mtch_sched[i].lcid_buffer_size/total_bytes_to_tx; float assigned_sfs = floor(sfs_per_sched_period*ratio); mch.mtch_sched[i].stop = last_mtch_stop + (uint32_t)assigned_sfs; last_mtch_stop = mch.mtch_sched[i].stop; - } + } }else { for(uint32_t i = 0; i < mch.num_mtch_sched;i++){ float assigned_sfs = ceil(((float)mch.mtch_sched[i].lcid_buffer_size)/((float)bytes_per_sf)); mch.mtch_sched[i].stop = last_mtch_stop + (uint32_t)assigned_sfs; - last_mtch_stop = mch.mtch_sched[i].stop; + last_mtch_stop = mch.mtch_sched[i].stop; } } } int mac::get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res) { - + srslte_ra_mcs_t mcs; srslte_ra_mcs_t mcs_data; mcs.idx = this->sib13.mbsfn_area_info_list_r9[0].signalling_mcs_r9; mcs_data.idx = this->mcch.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9; srslte_dl_fill_ra_mcs(&mcs, this->cell_config.cell.nof_prb); srslte_dl_fill_ra_mcs(&mcs_data, this->cell_config.cell.nof_prb); - if(is_mcch){ - + if(is_mcch){ + build_mch_sched(mcs_data.tbs); mch.mcch_payload = mcch_payload_buffer; mch.current_sf_allocation_num = 1; @@ -636,17 +708,17 @@ int mac::get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res) mch.pdu[i].lcid = srslte::sch_subh::MCH_SCHED_INFO; // mch.mtch_sched[i].lcid = 1+i; } - + mch.pdu[mch.num_mtch_sched].lcid = 0; mch.pdu[mch.num_mtch_sched].nbytes = current_mcch_length; dl_sched_res->sched_grants[0].rnti = SRSLTE_MRNTI; dl_sched_res->sched_grants[0].data[0] = ue_db[SRSLTE_MRNTI]->generate_mch_pdu(mch, mch.num_mtch_sched + 1, mcs.tbs/8); - + } else { uint32_t current_lcid = 1; uint32_t mtch_index = 0; uint32_t mtch_stop = mch.mtch_sched[mch.num_mtch_sched -1].stop; - + for(uint32_t i = 0;i < mch.num_mtch_sched;i++) { if(mch.current_sf_allocation_num <= mch.mtch_sched[i].stop){ current_lcid = mch.mtch_sched[i].lcid; @@ -669,9 +741,9 @@ int mac::get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res) } mch.current_sf_allocation_num++; } - + return SRSLTE_SUCCESS; -} +} uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32_t nof_grants, int rar_idx, uint32_t pdu_len) { @@ -684,10 +756,10 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32 if (pdu->new_subh()) { /* Search pending RAR */ int idx = grants[i].ra_id; - pdu->get()->set_rapid(pending_rars[idx].preamble_idx); + pdu->get()->set_rapid(pending_rars[idx].preamble_idx); pdu->get()->set_ta_cmd(pending_rars[idx].ta_cmd); - pdu->get()->set_temp_crnti(pending_rars[idx].temp_crnti); - pdu->get()->set_sched_grant(grant_buffer); + pdu->get()->set_temp_crnti(pending_rars[idx].temp_crnti); + pdu->get()->set_sched_grant(grant_buffer); bzero(&pending_rars[idx], sizeof(pending_rar_t)); } } @@ -695,76 +767,85 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32 return rar_payload[rar_idx]; } else { Error("Assembling RAR: pdu_len > rar_payload_len (%d>%d)\n", pdu_len, rar_payload_len); - return NULL; + return NULL; } } uint8_t* mac::assemble_si(uint32_t index) -{ +{ rlc_h->read_pdu_bcch_dlsch(index, bcch_dlsch_payload); return bcch_dlsch_payload; } -int mac::get_ul_sched(uint32_t tti, ul_sched_t *ul_sched_res) +int mac::get_ul_sched(uint32_t tti, ul_sched_t *ul_sched_res) { log_h->step(tti); - + if (!started) { - return 0; + return 0; } - + if (!ul_sched_res) { - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } - - // Run scheduler with current info - sched_interface::ul_sched_res_t sched_result; + + // Run scheduler with current info + sched_interface::ul_sched_res_t sched_result; bzero(&sched_result, sizeof(sched_interface::ul_sched_res_t)); if (scheduler.ul_sched(tti, &sched_result)<0) { Error("Running scheduler\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } - // Copy DCI grants - ul_sched_res->nof_grants = 0; - int n = 0; + pthread_rwlock_rdlock(&rwlock); + + // Copy DCI grants + ul_sched_res->nof_grants = 0; + int n = 0; for (uint32_t i=0;i 0) { - // Get UE + // Get UE uint16_t rnti = sched_result.pusch[i].rnti; - - // Copy grant info - ul_sched_res->sched_grants[n].rnti = rnti; - ul_sched_res->sched_grants[n].current_tx_nb = sched_result.pusch[i].current_tx_nb; - ul_sched_res->sched_grants[n].needs_pdcch = sched_result.pusch[i].needs_pdcch; - memcpy(&ul_sched_res->sched_grants[n].grant, &sched_result.pusch[i].dci, sizeof(srslte_ra_ul_dci_t)); - memcpy(&ul_sched_res->sched_grants[n].location, &sched_result.pusch[i].dci_location, sizeof(srslte_dci_location_t)); - - ul_sched_res->sched_grants[n].softbuffer = ue_db[rnti]->get_rx_softbuffer(tti); - - if (sched_result.pusch[n].current_tx_nb == 0) { - srslte_softbuffer_rx_reset_tbs(ul_sched_res->sched_grants[n].softbuffer, sched_result.pusch[i].tbs*8); + + if (ue_db.count(rnti)) { + // Copy grant info + ul_sched_res->sched_grants[n].rnti = rnti; + ul_sched_res->sched_grants[n].current_tx_nb = sched_result.pusch[i].current_tx_nb; + ul_sched_res->sched_grants[n].needs_pdcch = sched_result.pusch[i].needs_pdcch; + memcpy(&ul_sched_res->sched_grants[n].grant, &sched_result.pusch[i].dci, sizeof(srslte_ra_ul_dci_t)); + memcpy(&ul_sched_res->sched_grants[n].location, &sched_result.pusch[i].dci_location, sizeof(srslte_dci_location_t)); + + ul_sched_res->sched_grants[n].softbuffer = ue_db[rnti]->get_rx_softbuffer(tti); + + if (sched_result.pusch[n].current_tx_nb == 0) { + srslte_softbuffer_rx_reset_tbs(ul_sched_res->sched_grants[n].softbuffer, sched_result.pusch[i].tbs*8); + } + ul_sched_res->sched_grants[n].data = ue_db[rnti]->request_buffer(tti, sched_result.pusch[i].tbs); + ul_sched_res->nof_grants++; + n++; + } else { + Warning("Invalid DL scheduling result. User 0x%x does not exist\n", rnti); } - ul_sched_res->sched_grants[n].data = ue_db[rnti]->request_buffer(tti, sched_result.pusch[i].tbs); - ul_sched_res->nof_grants++; - n++; - + } else { Warning("Grant %d for rnti=0x%x has zero TBS\n", i, sched_result.pusch[i].rnti); } } + // No more uses of ue_db beyond here + pthread_rwlock_unlock(&rwlock); + // Copy PHICH actions for (uint32_t i=0;iphich[i].ack = sched_result.phich[i].phich == sched_interface::ul_sched_phich_t::ACK; - ul_sched_res->phich[i].rnti = sched_result.phich[i].rnti; + ul_sched_res->phich[i].rnti = sched_result.phich[i].rnti; } ul_sched_res->nof_phich = sched_result.nof_phich_elems; - return SRSLTE_SUCCESS; + return SRSLTE_SUCCESS; } - + void mac::tti_clock() { timers_thread.tti_clock(); @@ -799,7 +880,7 @@ srslte::timers::timer* mac::timer_get(uint32_t timer_id) *******************************************************/ void mac::timer_thread::run_thread() { - running=true; + running=true; ttisync.set_producer_cntr(0); ttisync.resync(); while(running) { @@ -829,34 +910,34 @@ void mac::timer_thread::tti_clock() * *******************************************************/ mac::pdu_process::pdu_process(pdu_process_handler *h) : running(false) { - handler = h; + handler = h; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cvar, NULL); - have_data = false; - start(MAC_PDU_THREAD_PRIO); + have_data = false; + start(MAC_PDU_THREAD_PRIO); } void mac::pdu_process::stop() { pthread_mutex_lock(&mutex); - running = false; + running = false; pthread_cond_signal(&cvar); pthread_mutex_unlock(&mutex); - + wait_thread_finish(); } void mac::pdu_process::notify() { pthread_mutex_lock(&mutex); - have_data = true; + have_data = true; pthread_cond_signal(&cvar); pthread_mutex_unlock(&mutex); } void mac::pdu_process::run_thread() { - running = true; + running = true; while(running) { have_data = handler->process_pdus(); if (!have_data) { @@ -871,13 +952,15 @@ void mac::pdu_process::run_thread() bool mac::process_pdus() { - bool ret = false; + pthread_rwlock_rdlock(&rwlock); + bool ret = false; for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - ue *u = iter->second; - uint16_t rnti = iter->first; + ue *u = iter->second; + uint16_t rnti = iter->first; ret = ret | u->process_pdus(); } - return ret; + pthread_rwlock_unlock(&rwlock); + return ret; } diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index b78157079..96e294339 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -57,22 +57,16 @@ sched::sched() : bc_aggr_level(0), rar_aggr_level(0), avail_rbg(0), P(0), start_ bzero(&sched_cfg, sizeof(sched_cfg)); bzero(&common_locations, sizeof(common_locations)); bzero(&pdsch_re, sizeof(pdsch_re)); - bzero(&mutex, sizeof(mutex)); for (int i = 0; i < 3; i++) { bzero(rar_locations[i], sizeof(sched_ue::sched_dci_cce_t) * 10); } - - pthread_mutex_init(&mutex, NULL); - pthread_mutex_init(&mutex2, NULL); reset(); } sched::~sched() { srslte_regs_free(®s); - pthread_mutex_destroy(&mutex); - pthread_mutex_destroy(&mutex2); } void sched::init(rrc_interface_mac *rrc_, srslte::log* log) @@ -118,8 +112,6 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg) return -1; } - pthread_mutex_lock(&mutex); - memcpy(&cfg, cell_cfg, sizeof(sched_interface::cell_cfg_t)); // Get DCI locations @@ -147,9 +139,7 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg) } configured = true; - pthread_mutex_unlock(&mutex); - - return 0; + return 0; } @@ -161,31 +151,24 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg) int sched::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t *ue_cfg) { - pthread_mutex_lock(&mutex); - - // Add or config user + // Add or config user ue_db[rnti].set_cfg(rnti, ue_cfg, &cfg, ®s, log_h); ue_db[rnti].set_max_mcs(sched_cfg.pusch_max_mcs, sched_cfg.pdsch_max_mcs); ue_db[rnti].set_fixed_mcs(sched_cfg.pusch_mcs, sched_cfg.pdsch_mcs); - pthread_mutex_unlock(&mutex); - return 0; + return 0; } int sched::ue_rem(uint16_t rnti) { - pthread_mutex_lock(&mutex); - pthread_mutex_lock(&mutex2); int ret = 0; - if (ue_db.count(rnti)) { + if (ue_db.count(rnti)) { ue_db.erase(rnti); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex2); - pthread_mutex_unlock(&mutex); - return ret; + return ret; } bool sched::ue_exists(uint16_t rnti) @@ -195,33 +178,27 @@ bool sched::ue_exists(uint16_t rnti) void sched::phy_config_enabled(uint16_t rnti, bool enabled) { - pthread_mutex_lock(&mutex); - if (ue_db.count(rnti)) { + if (ue_db.count(rnti)) { ue_db[rnti].phy_config_enabled(current_tti, enabled); } else { Error("User rnti=0x%x not found\n", rnti); } - pthread_mutex_unlock(&mutex); } int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_bearer_cfg(lc_id, cfg); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); return ret; } int sched::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) { - pthread_mutex_lock(&mutex); - pthread_mutex_lock(&mutex2); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].rem_bearer(lc_id); @@ -229,49 +206,33 @@ int sched::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex2); - pthread_mutex_unlock(&mutex); - return ret; + return ret; } uint32_t sched::get_dl_buffer(uint16_t rnti) { - pthread_mutex_lock(&mutex); - uint32_t ret = 0; + uint32_t ret = 0; if (ue_db.count(rnti)) { ret = ue_db[rnti].get_pending_dl_new_data(current_tti); } else { Error("User rnti=0x%x not found\n", rnti); } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } uint32_t sched::get_ul_buffer(uint16_t rnti) { - pthread_mutex_lock(&mutex); - uint32_t ret = 0; + uint32_t ret = 0; if (ue_db.count(rnti)) { ret = ue_db[rnti].get_pending_ul_new_data(current_tti); } else { Error("User rnti=0x%x not found\n", rnti); } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } -/* \Warning: This function is not mutexed because it can produce late changes on the buffer state while - * the scheduler is already allocating data, resulting in empty grants. - * Ideally we would like the scheduler to query the RLC for buffer states in order to get the most updated - * buffer state with the minimum overhead. However, the current architecture is designed to be compliant - * with the FAPI interface - * - * We add a new mutex used only in ue_rem to avoid the UE being removed in between the access to - * ue_db.count() and the access to the std::map. - */ int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { - pthread_mutex_lock(&mutex2); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].dl_buffer_state(lc_id, tx_queue, retx_queue); @@ -279,14 +240,11 @@ int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex2); return ret; } -/* \Warning Read comment in dl_rlc_buffer_state() */ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) { - pthread_mutex_lock(&mutex2); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].mac_buffer_state(ce_code); @@ -294,12 +252,10 @@ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex2); return ret; } int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { - pthread_mutex_lock(&mutex); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_dl_ant_info(dl_ant_info); @@ -307,55 +263,47 @@ int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT * Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); return ret; } int sched::dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ret = ue_db[rnti].set_ack_info(tti, tb_idx, ack); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_ul_crc(tti, crc); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_dl_ri(tti, cqi_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) { - pthread_mutex_lock(&mutex); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_dl_pmi(tti, pmi_value); @@ -363,13 +311,11 @@ int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); return ret; } int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { - pthread_mutex_lock(&mutex); int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_dl_cqi(tti, cqi_value); @@ -377,7 +323,6 @@ int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); return ret; } @@ -399,72 +344,62 @@ int sched::dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t es int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_ul_cqi(tti, cqi, ul_ch_code); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].ul_buffer_state(lcid, bsr, set_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].ul_recv_len(lcid, len); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::ul_phr(uint16_t rnti, int phr) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].ul_phr(phr); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } int sched::ul_sr_info(uint32_t tti, uint16_t rnti) { - pthread_mutex_lock(&mutex); - int ret = 0; + int ret = 0; if (ue_db.count(rnti)) { ue_db[rnti].set_sr();; } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } void sched::tpc_inc(uint16_t rnti) @@ -756,7 +691,6 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) if (!configured) { return 0; } - pthread_mutex_lock(&mutex); /* If ul_sched() not yet called this tti, reset CCE state */ if (current_tti != tti) { @@ -786,8 +720,7 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) /* Set CFI */ sched_result->cfi = current_cfi; - pthread_mutex_unlock(&mutex); - return 0; + return 0; } // Uplink sched @@ -798,8 +731,6 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched return 0; } - pthread_mutex_lock(&mutex); - /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ if (TTI_TX(current_tti) != tti) { bzero(used_cce, MAX_CCE*sizeof(bool)); @@ -858,14 +789,8 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched pucch.L = (uint32_t) cfg.nrb_pucch; if(!ul_metric->update_allocation(pucch)) { log_h->warning("SCHED: Failed to allocate PUCCH\n"); - } - for(it_t iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - sched_ue *user = (sched_ue *) &iter->second; - uint16_t rnti = (uint16_t) iter->first; - uint32_t prb_idx[2] = {0, 0}; - if(user->get_pucch_sched(current_tti, prb_idx)) { - user->has_pucch = true; - } + } else { + log_h->debug("Allocating PUCCH (%d,%d)\n", pucch.RB_start, pucch.RB_start+pucch.L); } } else { for(it_t iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { @@ -888,6 +813,10 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched ul_harq_proc::ul_alloc_t prach = {cfg.prach_freq_offset, 6}; if(!ul_metric->update_allocation(prach)) { log_h->warning("SCHED: Failed to allocate PRACH RBs within (%d,%d)\n", prach.RB_start, prach.RB_start + prach.L); + if (prach.RB_start + prach.L > cfg.cell.nof_prb) { + fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); + return -1; + } } else { log_h->debug("SCHED: Allocated PRACH RBs within (%d,%d)\n", prach.RB_start, prach.RB_start + prach.L); @@ -999,8 +928,6 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched sched_result->nof_dci_elems = nof_dci_elems; sched_result->nof_phich_elems = nof_phich_elems; - pthread_mutex_unlock(&mutex); - return SRSLTE_SUCCESS; } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 2eacf06f0..c852dc97c 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -60,15 +60,24 @@ sched_ue::sched_ue() : dl_next_alloc(NULL), ul_next_alloc(NULL), has_pucch(false bzero(&dl_harq, sizeof(dl_harq)); bzero(&ul_harq, sizeof(ul_harq)); bzero(&dl_ant_info, sizeof(dl_ant_info)); + + pthread_mutex_init(&mutex, NULL); reset(); } +sched_ue::~sched_ue() { + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + pthread_mutex_destroy(&mutex); +} + void sched_ue::set_cfg(uint16_t rnti_, sched_interface::ue_cfg_t *cfg_, sched_interface::cell_cfg_t *cell_cfg, srslte_regs_t *regs, srslte::log *log_h_) { reset(); - - rnti = rnti_; + + pthread_mutex_lock(&mutex); + rnti = rnti_; log_h = log_h_; memcpy(&cell, &cell_cfg->cell, sizeof(srslte_cell_t)); P = srslte_ra_type0_P(cell.nof_prb); @@ -81,11 +90,7 @@ void sched_ue::set_cfg(uint16_t rnti_, sched_interface::ue_cfg_t *cfg_, sched_in } Info("SCHED: Added user rnti=0x%x\n", rnti); - for (int i=0;i 4) { len -= 4; @@ -328,54 +389,72 @@ void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len) } Debug("SCHED: recv_len=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", len, lcid, lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); + + pthread_mutex_unlock(&mutex); } void sched_ue::set_ul_crc(uint32_t tti, bool crc_res) { + pthread_mutex_lock(&mutex); get_ul_harq(tti)->set_ack(0, crc_res); + pthread_mutex_unlock(&mutex); } void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) { + pthread_mutex_lock(&mutex); dl_ri = ri; dl_ri_tti = tti; + pthread_mutex_unlock(&mutex); } void sched_ue::set_dl_pmi(uint32_t tti, uint32_t pmi) { + pthread_mutex_lock(&mutex); dl_pmi = pmi; dl_pmi_tti = tti; + pthread_mutex_unlock(&mutex); } void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi) { + pthread_mutex_lock(&mutex); dl_cqi = cqi; dl_cqi_tti = tti; + pthread_mutex_unlock(&mutex); } void sched_ue::set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *d) { + pthread_mutex_lock(&mutex); memcpy(&dl_ant_info, d, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); + pthread_mutex_unlock(&mutex); } void sched_ue::set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code) { - ul_cqi = cqi; - ul_cqi_tti = tti; + pthread_mutex_lock(&mutex); + ul_cqi = cqi; + ul_cqi_tti = tti; + pthread_mutex_unlock(&mutex); } void sched_ue::tpc_inc() { + pthread_mutex_lock(&mutex); if (power_headroom > 0) { next_tpc_pusch = 3; next_tpc_pucch = 3; } log_h->info("SCHED: Set TCP=%d for rnti=0x%x\n", next_tpc_pucch, rnti); + pthread_mutex_unlock(&mutex); } void sched_ue::tpc_dec() { + pthread_mutex_lock(&mutex); next_tpc_pusch = 0; next_tpc_pucch = 0; log_h->info("SCHED: Set TCP=%d for rnti=0x%x\n", next_tpc_pucch, rnti); + pthread_mutex_unlock(&mutex); } /******************************************************* @@ -391,6 +470,8 @@ int sched_ue::generate_format1(dl_harq_proc *h, uint32_t tti, uint32_t cfi) { + pthread_mutex_lock(&mutex); + srslte_ra_dl_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_dl_dci_t)); @@ -410,7 +491,7 @@ int sched_ue::generate_format1(dl_harq_proc *h, } if (h->is_empty(0)) { - uint32_t req_bytes = get_pending_dl_new_data(tti); + uint32_t req_bytes = get_pending_dl_new_data_unlocked(tti); uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); srslte_ra_dl_grant_t grant; @@ -462,8 +543,9 @@ int sched_ue::generate_format1(dl_harq_proc *h, data->tbs[1] = 0; dci->tb_en[0] = true; dci->tb_en[1] = false; - } - return tbs; + } + pthread_mutex_unlock(&mutex); + return tbs; } // Generates a Format2a grant @@ -471,8 +553,21 @@ int sched_ue::generate_format2a(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi) +{ + pthread_mutex_lock(&mutex); + int ret = generate_format2a_unlocked(h, data, tti, cfi); + pthread_mutex_unlock(&mutex); + return ret; +} + +// Generates a Format2a grant +int sched_ue::generate_format2a_unlocked(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) { bool tb_en[SRSLTE_MAX_TB] = {false}; + srslte_ra_dl_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_dl_dci_t)); @@ -512,7 +607,7 @@ int sched_ue::generate_format2a(dl_harq_proc *h, } for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - uint32_t req_bytes = get_pending_dl_new_data(tti); + uint32_t req_bytes = get_pending_dl_new_data_unlocked(tti); int mcs = 0; int tbs = 0; @@ -566,17 +661,22 @@ int sched_ue::generate_format2a(dl_harq_proc *h, dci->tpc_pucch = (uint8_t) next_tpc_pucch; next_tpc_pucch = 1; - return data->tbs[0] + data->tbs[1]; + int ret = data->tbs[0] + data->tbs[1]; + return ret; } + // Generates a Format2 grant int sched_ue::generate_format2(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi) { + + pthread_mutex_lock(&mutex); + /* Call Format 2a (common) */ - int ret = generate_format2a(h, data, tti, cfi); + int ret = generate_format2a_unlocked(h, data, tti, cfi); /* Compute precoding information */ if (SRSLTE_RA_DL_GRANT_NOF_TB(&data->dci) == 1) { @@ -585,6 +685,8 @@ int sched_ue::generate_format2(dl_harq_proc *h, data->dci.pinfo = (uint8_t) (dl_pmi & 1); } + pthread_mutex_unlock(&mutex); + return ret; } @@ -594,7 +696,9 @@ int sched_ue::generate_format0(ul_harq_proc *h, uint32_t tti, bool cqi_request) { - srslte_ra_ul_dci_t *dci = &data->dci; + pthread_mutex_lock(&mutex); + + srslte_ra_ul_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_ul_dci_t)); int mcs = 0; @@ -608,7 +712,7 @@ int sched_ue::generate_format0(ul_harq_proc *h, h->new_tx(tti, mcs, tbs); } else if (h->is_empty(0)) { - uint32_t req_bytes = get_pending_ul_new_data(tti); + uint32_t req_bytes = get_pending_ul_new_data_unlocked(tti); uint32_t N_srs = 0; uint32_t nof_re = (2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs)*allocation.L*SRSLTE_NRE; @@ -645,8 +749,10 @@ int sched_ue::generate_format0(ul_harq_proc *h, dci->tpc_pusch = next_tpc_pusch; next_tpc_pusch = 1; } - - return tbs; + + pthread_mutex_unlock(&mutex); + + return tbs; } /******************************************************* @@ -678,37 +784,43 @@ bool sched_ue::is_first_dl_tx() } bool sched_ue::needs_cqi(uint32_t tti, bool will_be_sent) -{ - bool ret = false; - if (phy_config_dedicated_enabled && - cfg.aperiodic_cqi_period && - get_pending_dl_new_data(tti) > 0) +{ + pthread_mutex_lock(&mutex); + bool ret = needs_cqi_unlocked(tti, will_be_sent); + pthread_mutex_unlock(&mutex); + return ret; +} + +// Private lock-free implemenentation +bool sched_ue::needs_cqi_unlocked(uint32_t tti, bool will_be_sent) +{ + bool ret = false; + if (phy_config_dedicated_enabled && + cfg.aperiodic_cqi_period && + get_pending_dl_new_data_unlocked(tti) > 0) { - uint32_t interval = srslte_tti_interval(tti, dl_cqi_tti); + uint32_t interval = srslte_tti_interval(tti, dl_cqi_tti); bool needscqi = interval >= cfg.aperiodic_cqi_period; - if (needscqi) { - uint32_t interval_sent = srslte_tti_interval(tti, cqi_request_tti); + if (needscqi) { + uint32_t interval_sent = srslte_tti_interval(tti, cqi_request_tti); if (interval_sent >= 16) { if (will_be_sent) { - cqi_request_tti = tti; + cqi_request_tti = tti; } Debug("SCHED: Needs_cqi, last_sent=%d, will_be_sent=%d\n", cqi_request_tti, will_be_sent); - ret = true; - } + ret = true; + } } } - return ret; + return ret; } uint32_t sched_ue::get_pending_dl_new_data(uint32_t tti) { - uint32_t pending_data = 0; - for (int i=0;i0) { req_bytes += (req_bytes < 128) ? 2 : 3; // consider the header if(is_first_dl_tx()) { req_bytes += 6; // count for RAR } } + pthread_mutex_unlock(&mutex); return req_bytes; } +// Private lock-free implementation +uint32_t sched_ue::get_pending_dl_new_data_unlocked(uint32_t tti) +{ + uint32_t pending_data = 0; + for (int i=0;i pending_ul_data) { - pending_data -= pending_ul_data; + pending_data -= pending_ul_data; } else { - pending_data = 0; + pending_data = 0; } if (pending_data) { Debug("SCHED: pending_data=%d, pending_ul_data=%d, bsr={%d,%d,%d,%d}\n", pending_data,pending_ul_data, - lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); + lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); } - return pending_data; + return pending_data; } -uint32_t sched_ue::get_pending_ul_old_data() +// Private lock-free implementation +uint32_t sched_ue::get_pending_ul_old_data_unlocked() { - uint32_t pending_data = 0; + uint32_t pending_data = 0; for (int i=0;i 0) { nbytes = tbs; } else if (tbs < 0) { + pthread_mutex_unlock(&mutex); return 0; } } + pthread_mutex_unlock(&mutex); return n; } @@ -803,13 +951,15 @@ uint32_t sched_ue::get_required_prb_ul(uint32_t req_bytes) int mcs = 0; int tbs = 0; uint32_t nbytes = 0; - uint32_t N_srs = 0; - - uint32_t n = 0; + uint32_t N_srs = 0; + + uint32_t n = 0; if (req_bytes == 0) { return 0; } - + + pthread_mutex_lock(&mutex); + for (n=1;n= 0) { - return &dl_harq[oldest_idx]; - } else { - return NULL; + h = &dl_harq[oldest_idx]; } + + pthread_mutex_unlock(&mutex); + + return h; + #else return &dl_harq[tti%SCHED_MAX_HARQ_PROC]; #endif @@ -862,12 +1021,16 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_empty_dl_harq() { - for (int i=0;i max_coderate); Debug("SCHED: CQI=%d, l=%d, nof_bits=%d, coderate=%.2f, max_coderate=%.2f\n", dl_cqi, l, nof_bits, coderate, max_coderate); - return l; + pthread_mutex_unlock(&mutex); + return l; } sched_ue::sched_dci_cce_t* sched_ue::get_locations(uint32_t cfi, uint32_t sf_idx) @@ -955,7 +1120,7 @@ int sched_ue::alloc_pdu(int tbs_bytes, sched_interface::dl_sched_pdu_t* pdu) pdu->nbytes = x; Debug("SCHED: Allocated lcid=%d, nbytes=%d, tbs_bytes=%d\n", pdu->lcid, pdu->nbytes, tbs_bytes); } - return x; + return x; } uint32_t sched_ue::format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb) { @@ -1029,18 +1194,15 @@ int sched_ue::alloc_tbs(uint32_t nof_prb, uint32_t max_Qm = is_ul?4:6; // Allow 16-QAM in PUSCH Only // TODO: Compute real spectral efficiency based on PUSCH-UCI configuration - if (has_pucch && is_ul) { - cqi-=3; - } int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, max_Qm, &sel_mcs)/8; - + /* If less bytes are requested, lower the MCS */ if (tbs > (int) req_bytes && req_bytes > 0) { uint32_t req_tbs_idx = srslte_ra_tbs_to_table_idx(req_bytes*8, nof_prb); uint32_t req_mcs = srslte_ra_mcs_from_tbs_idx(req_tbs_idx); if (req_mcs < sel_mcs) { - sel_mcs = req_mcs; + sel_mcs = req_mcs; tbs = srslte_ra_tbs_from_idx(req_tbs_idx, nof_prb)/8; } } diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index f81331479..0731eda53 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -115,8 +115,7 @@ srslte_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t harq_process, uint32_t tb uint8_t* ue::request_buffer(uint32_t tti, uint32_t len) { uint8_t *ret = NULL; - pthread_mutex_lock(&mutex); - if (len > 0) { + if (len > 0) { if (!pending_buffers[tti%NOF_HARQ_PROCESSES]) { ret = pdus.request(len); pending_buffers[tti%NOF_HARQ_PROCESSES] = ret; @@ -127,8 +126,7 @@ uint8_t* ue::request_buffer(uint32_t tti, uint32_t len) } else { log_h->warning("Requesting buffer for zero bytes\n"); } - pthread_mutex_unlock(&mutex); - return ret; + return ret; } bool ue::process_pdus() diff --git a/srsenb/src/metrics_stdout.cc b/srsenb/src/metrics_stdout.cc index e80d7c158..826a03c92 100644 --- a/srsenb/src/metrics_stdout.cc +++ b/srsenb/src/metrics_stdout.cc @@ -41,6 +41,8 @@ using namespace std; namespace srsenb{ +#define MAX(a,b) (a>b?a:b) + char const * const prefixes[2][9] = { { "", "m", "u", "n", "p", "f", "a", "z", "y", }, @@ -125,25 +127,41 @@ void metrics_stdout::print_metrics() } cout << std::hex << metrics.mac[i].rnti << " "; - cout << float_to_string(metrics.mac[i].dl_cqi, 2); + cout << float_to_string(MAX(0.1,metrics.mac[i].dl_cqi), 2); cout << float_to_string(metrics.mac[i].dl_ri, 1); - cout << float_to_string(metrics.phy[i].dl.mcs, 2); - cout << float_to_eng_string((float) metrics.mac[i].tx_brate/metrics_report_period, 2); + if(not isnan(metrics.phy[i].dl.mcs)) { + cout << float_to_string(MAX(0.1,metrics.phy[i].dl.mcs), 2); + } else { + cout << float_to_string(0,2); + } + if (metrics.mac[i].tx_brate > 0 && metrics_report_period) { + cout << float_to_eng_string(MAX(0.1,(float) metrics.mac[i].tx_brate/metrics_report_period), 2); + } else { + cout << float_to_string(0, 2) << ""; + } if (metrics.mac[i].tx_pkts > 0 && metrics.mac[i].tx_errors) { - cout << float_to_string((float) 100*metrics.mac[i].tx_errors/metrics.mac[i].tx_pkts, 1) << "%"; + cout << float_to_string(MAX(0.1,(float) 100*metrics.mac[i].tx_errors/metrics.mac[i].tx_pkts), 1) << "%"; } else { cout << float_to_string(0, 1) << "%"; } - cout << float_to_string(metrics.phy[i].ul.sinr, 2); + if(not isnan(metrics.phy[i].ul.sinr)) { + cout << float_to_string(MAX(0.1,metrics.phy[i].ul.sinr), 2); + } else { + cout << float_to_string(0,2); + } cout << float_to_string(metrics.mac[i].phr, 2); - cout << float_to_string(metrics.phy[i].ul.mcs, 2); + if(not isnan(metrics.phy[i].ul.mcs)) { + cout << float_to_string(MAX(0.1,metrics.phy[i].ul.mcs), 2); + } else { + cout << float_to_string(0,2); + } if (metrics.mac[i].rx_brate > 0 && metrics_report_period) { - cout << float_to_eng_string((float) metrics.mac[i].rx_brate/metrics_report_period, 2); + cout << float_to_eng_string(MAX(0.1,(float) metrics.mac[i].rx_brate/metrics_report_period), 2); } else { - cout << " " << float_to_string(0, 2); + cout << float_to_string(0, 2) << ""; } if (metrics.mac[i].rx_pkts > 0 && metrics.mac[i].rx_errors > 0) { - cout << float_to_string((float) 100*metrics.mac[i].rx_errors/metrics.mac[i].rx_pkts, 1) << "%"; + cout << float_to_string(MAX(0.1,(float) 100*metrics.mac[i].rx_errors/metrics.mac[i].rx_pkts), 1) << "%"; } else { cout << float_to_string(0, 1) << "%"; } diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 13156d651..36a260b6c 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -39,10 +39,10 @@ using namespace std; // Enable this to log SI -#define LOG_THIS(a) 1 +//#define LOG_THIS(a) 1 // Enable this one to skip SI-RNTI -//#define LOG_THIS(rnti) (rnti != 0xFFFF) +#define LOG_THIS(rnti) (rnti != 0xFFFF) /* Define GUI-related things */ @@ -185,11 +185,11 @@ void phch_worker::stop() free(signal_buffer_tx[p]); } } - pthread_mutex_unlock(&mutex); - pthread_mutex_destroy(&mutex); } else { printf("Warning could not stop properly PHY\n"); } + pthread_mutex_unlock(&mutex); + pthread_mutex_destroy(&mutex); } void phch_worker::reset() { @@ -372,9 +372,10 @@ void phch_worker::work_imp() subframe_cfg_t sf_cfg; phy->get_sf_config(&sf_cfg, tti_tx_dl);// TODO difference between tti_tx_dl and t_tx_dl + pthread_mutex_lock(&mutex); is_worker_running = true; - + mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; mac_interface_phy *mac = phy->mac; @@ -398,7 +399,7 @@ void phch_worker::work_imp() decode_pucch(); // Get DL scheduling for the TX TTI from MAC - + if(sf_cfg.sf_type == SUBFRAME_TYPE_REGULAR) { if (mac->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) { Error("Getting DL scheduling from MAC\n"); diff --git a/srsenb/src/upper/pdcp.cc b/srsenb/src/upper/pdcp.cc index e6f4f40f5..6f07e4ece 100644 --- a/srsenb/src/upper/pdcp.cc +++ b/srsenb/src/upper/pdcp.cc @@ -37,18 +37,24 @@ void pdcp::init(rlc_interface_pdcp* rlc_, rrc_interface_pdcp* rrc_, gtpu_interfa log_h = pdcp_log_; pool = srslte::byte_buffer_pool::get_instance(); + + pthread_rwlock_init(&rwlock, NULL); } void pdcp::stop() { + pthread_rwlock_wrlock(&rwlock); for(std::map::iterator iter=users.begin(); iter!=users.end(); ++iter) { - rem_user((uint32_t) iter->first); + clear_user(&iter->second); } users.clear(); + pthread_rwlock_unlock(&rwlock); + pthread_rwlock_destroy(&rwlock); } void pdcp::add_user(uint16_t rnti) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti) == 0) { srslte::pdcp *obj = new srslte::pdcp; obj->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].gtpu_itf, log_h, RB_ID_SRB0, SECURITY_DIRECTION_DOWNLINK); @@ -61,20 +67,30 @@ void pdcp::add_user(uint16_t rnti) users[rnti].gtpu_itf.gtpu = gtpu; users[rnti].pdcp = obj; } + pthread_rwlock_unlock(&rwlock); +} + +// Private unlocked deallocation of user +void pdcp::clear_user(user_interface *ue) +{ + ue->pdcp->stop(); + delete ue->pdcp; + ue->pdcp = NULL; } void pdcp::rem_user(uint16_t rnti) { + pthread_rwlock_wrlock(&rwlock); if (users.count(rnti)) { - users[rnti].pdcp->stop(); - delete users[rnti].pdcp; - users[rnti].pdcp = NULL; + clear_user(&users[rnti]); users.erase(rnti); } + pthread_rwlock_unlock(&rwlock); } void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ users[rnti].pdcp->add_bearer(lcid, cfg); @@ -82,37 +98,45 @@ void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t users[rnti].pdcp->add_bearer_mrb(lcid, cfg); } } + pthread_rwlock_unlock(&rwlock); } void pdcp::reset(uint16_t rnti) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].pdcp->reset(); } + pthread_rwlock_unlock(&rwlock); } void pdcp::config_security(uint16_t rnti, uint32_t lcid, uint8_t* k_rrc_enc_, uint8_t* k_rrc_int_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].pdcp->config_security(lcid, k_rrc_enc_, k_rrc_int_, cipher_algo_, integ_algo_); users[rnti].pdcp->enable_integrity(lcid); users[rnti].pdcp->enable_encryption(lcid); } + pthread_rwlock_unlock(&rwlock); } void pdcp::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].pdcp->write_pdu(lcid, sdu); } else { pool->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ users[rnti].pdcp->write_sdu(lcid, sdu); @@ -122,6 +146,7 @@ void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) } else { pool->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index 0624dbca4..d02ee6c7c 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -40,48 +40,57 @@ void rlc::init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface pool = srslte::byte_buffer_pool::get_instance(); + pthread_rwlock_init(&rwlock, NULL); } void rlc::stop() { + pthread_rwlock_wrlock(&rwlock); for(std::map::iterator iter=users.begin(); iter!=users.end(); ++iter) { - rem_user((uint32_t) iter->first); + clear_user(&iter->second); } users.clear(); + pthread_rwlock_unlock(&rwlock); + pthread_rwlock_destroy(&rwlock); } void rlc::add_user(uint16_t rnti) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti) == 0) { srslte::rlc *obj = new srslte::rlc; - obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0); + obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0, RLC_TX_QUEUE_LEN); users[rnti].rnti = rnti; users[rnti].pdcp = pdcp; users[rnti].rrc = rrc; users[rnti].rlc = obj; users[rnti].parent = this; } + pthread_rwlock_unlock(&rwlock); } -void rlc::rem_user(uint16_t rnti) +// Private unlocked deallocation of user +void rlc::clear_user(user_interface *ue) { - if (users.count(rnti)) { - users[rnti].rlc->stop(); - delete users[rnti].rlc; - users[rnti].rlc = NULL; - users.erase(rnti); - } + ue->rlc->stop(); + delete ue->rlc; + ue->rlc = NULL; } - -void rlc::reset(uint16_t rnti) +void rlc::rem_user(uint16_t rnti) { + pthread_rwlock_wrlock(&rwlock); if (users.count(rnti)) { - users[rnti].rlc->reset(); + clear_user(&users[rnti]); + users.erase(rnti); + } else { + log_h->error("Removing rnti=0x%x. Already removed\n", rnti); } + pthread_rwlock_unlock(&rwlock); } void rlc::clear_buffer(uint16_t rnti) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].rlc->empty_queue(); for (int i=0;iinfo("Cleared buffer rnti=0x%x\n", rnti); } + pthread_rwlock_unlock(&rwlock); } void rlc::add_bearer(uint16_t rnti, uint32_t lcid) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].rlc->add_bearer(lcid); } + pthread_rwlock_unlock(&rwlock); } void rlc::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].rlc->add_bearer(lcid, cnfg); } + pthread_rwlock_unlock(&rwlock); } void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].rlc->add_bearer_mrb_enb(lcid); } + pthread_rwlock_unlock(&rwlock); } void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) @@ -121,11 +137,13 @@ int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_b { int ret; uint32_t tx_queue; - if(users.count(rnti)){ - if(rnti != SRSLTE_MRNTI){ + + pthread_rwlock_rdlock(&rwlock); + if(users.count(rnti)) { + if(rnti != SRSLTE_MRNTI) { ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes); tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); - }else{ + } else { ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes); tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid); } @@ -135,15 +153,16 @@ int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_b uint32_t retx_queue = 0; log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue); mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); - return ret; - }else{ - return SRSLTE_ERROR; + ret = SRSLTE_ERROR; } + pthread_rwlock_unlock(&rwlock); + return ret; } void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { users[rnti].rlc->write_pdu(lcid, payload, nof_bytes); @@ -154,6 +173,7 @@ void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue); mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); } + pthread_rwlock_unlock(&rwlock); } void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t *payload) @@ -166,9 +186,11 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { uint32_t tx_queue; + + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ - users[rnti].rlc->write_sdu(lcid, sdu); + users[rnti].rlc->write_sdu_nb(lcid, sdu); tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); }else { users[rnti].rlc->write_sdu_mch(lcid, sdu); @@ -183,14 +205,17 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) } else { pool->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) { + bool ret = false; + pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { - return users[rnti].rlc->rb_is_um(lcid); - } else { - return false; + ret = users[rnti].rlc->rb_is_um(lcid); } + pthread_rwlock_unlock(&rwlock); + return ret; } void rlc::user_interface::max_retx_attempted() diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 770685165..642a515af 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -84,7 +84,8 @@ void rrc::stop() { if(running) { running = false; - thread_cancel(); + rrc_pdu p = {0, LCID_EXIT, NULL}; + rx_pdu_queue.push(p); wait_thread_finish(); } act_monitor.stop(); @@ -585,8 +586,7 @@ void rrc::process_release_complete(uint16_t rnti) // There is no RRCReleaseComplete message from UE thus wait ~50 subframes for tx usleep(50000); } - // Save to call rem_user() directly without thread, because calling from private function - rem_user(rnti); + rem_user_thread(rnti); } else { rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); } @@ -594,6 +594,7 @@ void rrc::process_release_complete(uint16_t rnti) void rrc::rem_user(uint16_t rnti) { + pthread_mutex_lock(&user_mutex); if (users.count(rnti) == 1) { rrc_log->console("Disconnecting rnti=0x%x.\n", rnti); rrc_log->info("Disconnecting rnti=0x%x.\n", rnti); @@ -603,11 +604,6 @@ void rrc::rem_user(uint16_t rnti) mac->ue_rem(rnti); // MAC handles PHY gtpu->rem_user(rnti); - // Wait enough time - pthread_mutex_unlock(&user_mutex); - usleep(50000); - pthread_mutex_lock(&user_mutex); - // Now remove RLC and PDCP rlc->rem_user(rnti); pdcp->rem_user(rnti); @@ -615,11 +611,13 @@ void rrc::rem_user(uint16_t rnti) // And deallocate resources from RRC users[rnti].sr_free(); users[rnti].cqi_free(); + users.erase(rnti); rrc_log->info("Removed user rnti=0x%x\n", rnti); } else { rrc_log->error("Removing user rnti=0x%x (does not exist)\n", rnti); } + pthread_mutex_unlock(&user_mutex); } void rrc::config_mac() @@ -778,7 +776,6 @@ void rrc::run_thread() } // Mutex these calls even though it's a private function - pthread_mutex_lock(&user_mutex); if (users.count(p.rnti) == 1) { switch(p.lcid) { @@ -803,6 +800,9 @@ void rrc::run_thread() users[p.rnti].set_activity(); } break; + case LCID_EXIT: + rrc_log->info("Exiting thread\n"); + break; default: rrc_log->error("Rx PDU with invalid bearer id: %d", p.lcid); break; @@ -810,7 +810,6 @@ void rrc::run_thread() } else { rrc_log->warning("Discarding PDU for removed rnti=0x%x\n", p.rnti); } - pthread_mutex_unlock(&user_mutex); } } @@ -863,7 +862,7 @@ void rrc::activity_monitor::run_thread() parent->s1ap->user_release(rem_rnti, LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY); } else { if(rem_rnti != SRSLTE_MRNTI) - parent->rem_user(rem_rnti); + parent->rem_user_thread(rem_rnti); } } pthread_mutex_unlock(&parent->user_mutex); From ebea1cd7fad62dd5f6275b1f73a5f1667f52ff53 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 12:03:26 +0200 Subject: [PATCH 16/28] Look only for required SIBs --- srsue/hdr/upper/rrc.h | 2 -- srsue/src/upper/rrc.cc | 31 +++++++++++++++++-------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 33acf8b7c..dfef5e723 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -447,8 +447,6 @@ private: uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf); const static int SIB_SEARCH_TIMEOUT_MS = 1000; - const static uint32_t NOF_REQUIRED_SIBS = 13; // SIB1, SIB2 and SIB3 - bool initiated; bool ho_start; bool go_idle; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index dca64708f..66a7de33e 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -41,6 +41,8 @@ using namespace srslte; namespace srsue { +const static uint32_t NOF_REQUIRED_SIBS = 4; +const static uint32_t required_sibs[NOF_REQUIRED_SIBS] = {0,1,2,12}; // SIB1, SIB2, SIB3 and SIB13 (eMBMS) /******************************************************************************* Base functions @@ -543,24 +545,25 @@ bool rrc::configure_serving_cell() { return false; } serving_cell->has_mcch = false; - // Apply configurations if already retrieved SIB2 - if (serving_cell->has_sib2()) { - apply_sib2_configs(serving_cell->sib2ptr()); - } - // Obtain the rest of required SIBs (configuration is applied when received) + // Obtain the SIBs if not available or apply the configuration if available for (uint32_t i = 0; i < NOF_REQUIRED_SIBS; i++) { - if (!serving_cell->has_sib(i)) { - rrc_log->info("Cell has no SIB%d. Obtaining SIB%d\n", i+1, i+1); - if (!si_acquire(i)) { - rrc_log->info("Timeout while acquiring SIB%d\n", i+1); - if (i < 2) { + if (!serving_cell->has_sib(required_sibs[i])) { + rrc_log->info("Cell has no SIB%d. Obtaining SIB%d\n", required_sibs[i]+1, required_sibs[i]+1); + if (!si_acquire(required_sibs[i])) { + rrc_log->info("Timeout while acquiring SIB%d\n", required_sibs[i]+1); + if (required_sibs[i] < 2) { return false; } } } else { - rrc_log->info("Cell has SIB%d\n", i+1); - if(i+1 == 13){ - apply_sib13_configs(serving_cell->sib13ptr()); + rrc_log->info("Cell has SIB%d\n", required_sibs[i]+1); + switch(required_sibs[i]) { + case 1: + apply_sib2_configs(serving_cell->sib2ptr()); + break; + case 12: + apply_sib13_configs(serving_cell->sib13ptr()); + break; } } } @@ -768,7 +771,7 @@ bool rrc::si_acquire(uint32_t sib_index) } } if (!found) { - rrc_log->error("Could not find SIB%d scheduling in SIB1\n", sib_index+1); + rrc_log->info("Could not find SIB%d scheduling in SIB1\n", sib_index+1); return false; } } From c64e26559ef800b206c9af6f8a526e2ac184ab2a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 14:08:23 +0200 Subject: [PATCH 17/28] Dropped PDU log level to info --- lib/src/upper/rlc_am.cc | 2 +- lib/src/upper/rlc_tm.cc | 2 +- lib/src/upper/rlc_um.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 51aeb6a34..26f91d84b 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -210,7 +210,7 @@ void rlc_am::write_sdu_nb(byte_buffer_t *sdu) if (tx_sdu_queue.try_write(sdu)) { log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); } else { - log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + log->info_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); pool->deallocate(sdu); } } else { diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 9c367dada..2260ea2bc 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -113,7 +113,7 @@ void rlc_tm::write_sdu_nb(byte_buffer_t *sdu) log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); } else { - log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d", + log->info_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d", rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); pool->deallocate(sdu); } diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 190380675..d5ce7093c 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -206,7 +206,7 @@ void rlc_um::write_sdu_nb(byte_buffer_t *sdu) if (tx_sdu_queue.try_write(sdu)) { log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); } else { - log->warning_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + log->info_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B ,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); pool->deallocate(sdu); } } else { From cf5a6f058061f92f01962dc04044ba0fccd24d7c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 14:09:46 +0200 Subject: [PATCH 18/28] Increased PUCCH RLF threshold and default number of errors --- srsenb/hdr/phy/phch_worker.h | 2 +- srsenb/src/main.cc | 2 +- srsenb/src/upper/rrc.cc | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index a0ee6fd91..776ba0a1b 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -71,7 +71,7 @@ public: private: const static float PUSCH_RL_SNR_DB_TH = 1.0; - const static float PUCCH_RL_CORR_TH = 0.1; + const static float PUCCH_RL_CORR_TH = 0.15; void work_imp(); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index e9b94d531..a993ebd3e 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -167,7 +167,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { "Number of PHY threads") ("expert.link_failure_nof_err", - bpo::value(&args->expert.mac.link_failure_nof_err)->default_value(50), + bpo::value(&args->expert.mac.link_failure_nof_err)->default_value(100), "Number of PUSCH failures after which a radio-link failure is triggered") ("expert.max_prach_offset_us", diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 642a515af..3a9bbd0f2 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -557,7 +557,7 @@ void rrc::parse_ul_dcch(uint16_t rnti, uint32_t lcid, byte_buffer_t *pdu) void rrc::process_rl_failure(uint16_t rnti) { - if (users.count(rnti) == 0) { + if (users.count(rnti) == 1) { uint32_t n_rfl = users[rnti].rl_failure(); if (n_rfl == 1) { rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti); @@ -573,6 +573,8 @@ void rrc::process_rl_failure(uint16_t rnti) } else { rrc_log->info("%d Radio-Link failure detected rnti=0x%x\n", n_rfl, rnti); } + } else { + rrc_log->error("Radio-Link failure detected for uknown rnti=0x%x\n", rnti); } } From 19ac35d9333bc8d41e6e9f67a31244ecc56766c9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 18:11:47 +0200 Subject: [PATCH 19/28] Increased RLC UL buffer size --- lib/src/upper/rlc_entity.cc | 2 +- srsenb/hdr/mac/scheduler_ue.h | 1 + srsenb/rr.conf.example | 8 ++++---- srsenb/sib.conf.example | 4 ++-- srsenb/src/mac/mac.cc | 2 +- srsenb/src/mac/scheduler.cc | 10 ++++++++-- srsenb/src/mac/scheduler_ue.cc | 15 ++++++++++++++- srsenb/src/mac/ue.cc | 4 ++-- srsue/src/mac/proc_bsr.cc | 11 ++++++----- 9 files changed, 39 insertions(+), 18 deletions(-) diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index 9ac526868..762f853d6 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -43,7 +43,7 @@ void rlc_entity::init(rlc_mode_t mode_, { if (buffer_size <= 0) { - buffer_size = 16; + buffer_size = 64; } // Create the RLC instance the first time init() is called. // If called to reestablished, the entity is stopped but not destroyed diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 84afd8c7f..202ef8bd0 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -111,6 +111,7 @@ public: uint32_t get_pending_ul_old_data(); uint32_t get_pending_dl_new_data_total(uint32_t tti); + void reset_timeout_dl_harq(uint32_t tti); dl_harq_proc *get_pending_dl_harq(uint32_t tti); dl_harq_proc *get_empty_dl_harq(); ul_harq_proc *get_ul_harq(uint32_t tti); diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index af6dcf2c1..e819cf4e4 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -9,7 +9,7 @@ mac_cnfg = ulsch_cnfg = { max_harq_tx = 4; - periodic_bsr_timer = 40; // in ms + periodic_bsr_timer = 20; // in ms retx_bsr_timer = 320; // in ms }; @@ -26,9 +26,9 @@ phy_cnfg = pusch_cnfg_ded = { - beta_offset_ack_idx = 10; - beta_offset_ri_idx = 5; - beta_offset_cqi_idx = 10; + beta_offset_ack_idx = 6; + beta_offset_ri_idx = 6; + beta_offset_cqi_idx = 6; }; // PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource. diff --git a/srsenb/sib.conf.example b/srsenb/sib.conf.example index 631f32e03..dded32c7c 100644 --- a/srsenb/sib.conf.example +++ b/srsenb/sib.conf.example @@ -47,13 +47,13 @@ sib2 = high_speed_flag = false; prach_config_index = 3; prach_freq_offset = 2; - zero_correlation_zone_config = 11; + zero_correlation_zone_config = 5; }; }; pdsch_cnfg = { p_b = 0; - rs_power = -10; + rs_power = 0; }; pusch_cnfg = { diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 02b5686a5..580201add 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -332,7 +332,7 @@ int mac::ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) if (ack) { if (nof_bytes > 64) { // do not count RLC status messages only rrc_h->set_activity_user(rnti); - log_h->info("DL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); + log_h->debug("DL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); } } pthread_rwlock_unlock(&rwlock); diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 96e294339..026c85559 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -679,8 +679,14 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) } Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d, cfi=%d\n", rnti, h->get_id(), current_cfi); } - } - } + } + + // Reset blocked PIDs + user->reset_timeout_dl_harq(current_tti); + + } + + return nof_data_elems; } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index c852dc97c..d96cbdda2 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -383,7 +383,7 @@ void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len) if (lch[lcid].bsr > (int) len) { lch[lcid].bsr -= len; } else { - lch[lcid].bsr = 0; + lch[lcid].bsr = 0; } } } @@ -987,6 +987,19 @@ bool sched_ue::is_sr_triggered() return sr; } +void sched_ue::reset_timeout_dl_harq(uint32_t tti) { + for (int i=0;iinfo("SCHED: pid=%d is empty\n", i); + if (srslte_tti_interval(tti, dl_harq[i].get_tti()) > 50) { + log_h->info("SCHED: pid=%d is old. tti_pid=%d, now is %d, resetting\n", i, dl_harq[i].get_tti(), tti); + dl_harq[i].reset(0); + dl_harq[i].reset(1); + } + } + } +} + /* Gets HARQ process with oldest pending retx */ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) { diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index 0731eda53..9a5424538 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -188,12 +188,12 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channe } // Indicate scheduler to update BSR counters - sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); + //sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); // Indicate RRC about successful activity if valid RLC message is received if (mac_msg_ul.get()->get_payload_size() > 64) { // do not count RLC status messages only rrc->set_activity_user(rnti); - log_h->info("UL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); + log_h->debug("UL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); } if ((int) mac_msg_ul.get()->get_payload_size() > most_data) { diff --git a/srsue/src/mac/proc_bsr.cc b/srsue/src/mac/proc_bsr.cc index 19b214a74..bd49671df 100644 --- a/srsue/src/mac/proc_bsr.cc +++ b/srsue/src/mac/proc_bsr.cc @@ -209,7 +209,11 @@ bool bsr_proc::generate_bsr(bsr_t *bsr, uint32_t nof_padding_bytes) { if (nof_lcg > 1) { bsr->format = LONG_BSR; } - } + } + Info("BSR: Type %s, Format %s, Value=%d,%d,%d,%d\n", + bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format), + bsr->buff_size[0], bsr->buff_size[1], bsr->buff_size[2], bsr->buff_size[3]); + return ret; } @@ -337,10 +341,7 @@ bool bsr_proc::generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) } generate_bsr(bsr, nof_padding_bytes); ret = true; - Info("BSR: Type %s, Format %s, Value=%d,%d,%d,%d\n", - bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format), - bsr->buff_size[0], bsr->buff_size[1], bsr->buff_size[2], bsr->buff_size[3]); - + if (timers_db->get(timer_periodic_id)->get_timeout() && bsr->format != TRUNC_BSR) { timers_db->get(timer_periodic_id)->reset(); timers_db->get(timer_periodic_id)->run(); From f40766a5037e0388c63019db7539b69aee20c548 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 5 Jul 2018 18:38:31 +0200 Subject: [PATCH 20/28] Fixed UE not printing RF metrics --- srsue/src/ue.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index e9078a1cd..5c71422d2 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -322,7 +322,6 @@ bool ue::get_metrics(ue_metrics_t &m) bzero(&rf_metrics, sizeof(rf_metrics_t)); rf_metrics.rf_error = false; // Reset error flag - bzero(&m, sizeof(ue_metrics_t)); if(EMM_STATE_REGISTERED == nas.get_state()) { if(RRC_STATE_CONNECTED == rrc.get_state()) { phy.get_metrics(m.phy); From 85a7daa09df6ed5c9ed2546b61c6d341c5f963a9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 6 Jul 2018 09:08:29 +0200 Subject: [PATCH 21/28] Move RLC buffer size to common --- lib/include/srslte/upper/rlc_common.h | 4 ++++ lib/src/upper/rlc_entity.cc | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index bfc21f711..a5b2e0403 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -151,6 +151,10 @@ struct rlc_status_pdu_t{ class rlc_common { public: + + // Size of the Uplink buffer in number of PDUs + const static int RLC_BUFFER_NOF_PDU = 128; + virtual ~rlc_common() {} virtual void init(srslte::log *rlc_entity_log_, uint32_t lcid_, diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index 762f853d6..4d0573043 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -43,7 +43,7 @@ void rlc_entity::init(rlc_mode_t mode_, { if (buffer_size <= 0) { - buffer_size = 64; + buffer_size = rlc_common::RLC_BUFFER_NOF_PDU; } // Create the RLC instance the first time init() is called. // If called to reestablished, the entity is stopped but not destroyed From a38abfbd47605922e7d859322cfccfff01f33dcd Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Jul 2018 09:40:53 +0200 Subject: [PATCH 22/28] make metrics great again --- srsue/src/ue.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 5c71422d2..1218a322c 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -318,6 +318,7 @@ void ue::print_pool() { bool ue::get_metrics(ue_metrics_t &m) { + bzero(&m, sizeof(ue_metrics_t)); m.rf = rf_metrics; bzero(&rf_metrics, sizeof(rf_metrics_t)); rf_metrics.rf_error = false; // Reset error flag From d7e4797f3f5275a92eef0f2bd7132d305fe758bf Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Jul 2018 11:09:56 +0200 Subject: [PATCH 23/28] add rf error handler in soapy --- lib/src/phy/rf/rf_soapy_imp.c | 54 ++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index b6260f21a..359092d28 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -62,6 +62,8 @@ typedef struct { double tx_rate; size_t rx_mtu, tx_mtu; + srslte_rf_error_handler_t soapy_error_handler; + uint32_t num_time_errors; uint32_t num_lates; uint32_t num_overflows; @@ -74,6 +76,41 @@ typedef struct { cf_t zero_mem[64*1024]; +static void log_overflow(rf_soapy_handler_t *h) { + if (h->soapy_error_handler) { + srslte_rf_error_t error; + bzero(&error, sizeof(srslte_rf_error_t)); + error.type = SRSLTE_RF_ERROR_OVERFLOW; + h->soapy_error_handler(error); + } else { + h->num_overflows++; + } +} + +static void log_late(rf_soapy_handler_t *h, bool is_rx) { + if (h->soapy_error_handler) { + srslte_rf_error_t error; + bzero(&error, sizeof(srslte_rf_error_t)); + error.opt = is_rx?1:0; + error.type = SRSLTE_RF_ERROR_LATE; + h->soapy_error_handler(error); + } else { + h->num_lates++; + } +} + +static void log_underflow(rf_soapy_handler_t *h) { + if (h->soapy_error_handler) { + srslte_rf_error_t error; + bzero(&error, sizeof(srslte_rf_error_t)); + error.type = SRSLTE_RF_ERROR_UNDERFLOW; + h->soapy_error_handler(error); + } else { + h->num_underflows++; + } +} + + int soapy_error(void *h) { return 0; @@ -104,9 +141,10 @@ void rf_soapy_suppress_stdout(void *h) } -void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t new_handler) +void rf_soapy_register_error_handler(void *h, srslte_rf_error_handler_t new_handler) { - // not supported + rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + handler->soapy_error_handler = new_handler; } @@ -647,15 +685,11 @@ int rf_soapy_recv_with_time_multi(void *h, ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr, rx_samples, &flags, &timeNs, timeoutUs); if (ret == SOAPY_SDR_OVERFLOW || (ret > 0 && (flags & SOAPY_SDR_END_ABRUPT) != 0)) { - handler->num_overflows++; - fprintf(stderr, "O"); - fflush(stderr); + log_overflow(handler); continue; } else if (ret == SOAPY_SDR_TIMEOUT) { - handler->num_time_errors++; - fprintf(stderr, "T"); - fflush(stderr); + log_late(handler, true); continue; } else if (ret < 0) { @@ -792,7 +826,7 @@ int rf_soapy_send_timed_multi(void *h, // An error has occured switch (ret) { case SOAPY_SDR_TIMEOUT: - handler->num_lates++; + log_late(handler, false); printf("L"); break; case SOAPY_SDR_STREAM_ERROR: @@ -804,7 +838,7 @@ int rf_soapy_send_timed_multi(void *h, printf("T"); break; case SOAPY_SDR_UNDERFLOW: - handler->num_underflows++; + log_underflow(handler); printf("U"); break; default: From 9ef12859b0f3b236c0dc73d578dbe990f14dfdff Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Jul 2018 11:10:26 +0200 Subject: [PATCH 24/28] register rf error handler in radio benchmark --- lib/src/radio/test/benchmark_radio.cc | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/src/radio/test/benchmark_radio.cc b/lib/src/radio/test/benchmark_radio.cc index db3371cd7..d15adaa6b 100644 --- a/lib/src/radio/test/benchmark_radio.cc +++ b/lib/src/radio/test/benchmark_radio.cc @@ -40,6 +40,11 @@ double duration = 0.01; /* in seconds, 10 ms by default */ cf_t *buffers[SRSLTE_MAX_PORTS]; bool tx_enable = false; +uint32_t num_lates = 0; +uint32_t num_overflows = 0; +uint32_t num_underflows = 0; +uint32_t num_other_error = 0; + void usage(char *prog) { printf("Usage: %s [rpstvh]\n", prog); @@ -97,6 +102,29 @@ void sig_int_handler(int signo) } } +void rf_msg(srslte_rf_error_t error) +{ + if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) { + num_overflows++; + } else + if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_UNDERFLOW) { + num_underflows++; + } else + if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_LATE) { + num_lates++; + } else { + num_other_error++; + } +} + +void print_rf_summary(void) +{ + printf("#lates=%d\n", num_lates); + printf("#overflows=%d\n", num_overflows); + printf("#underflows=%d\n", num_underflows); + printf("#num_other_error=%d\n", num_other_error); +} + int main(int argc, char **argv) { int ret = SRSLTE_ERROR; @@ -137,6 +165,8 @@ int main(int argc, char **argv) goto clean_exit; } + radio_h->register_error_handler(rf_msg); + radio_h->set_rx_freq(freq); /* Set radio */ @@ -194,5 +224,7 @@ clean_exit: printf("Ok!\n"); } + print_rf_summary(); + return ret; } From 1dc58363651a926240b8bf7e2036f4313e2a6369 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 6 Jul 2018 11:52:04 +0100 Subject: [PATCH 25/28] Adding SGi-mb mask to config --- srsepc/hdr/mbms-gw/mbms-gw.h | 1 + srsepc/mbms.conf.example | 3 ++- srsepc/src/mbms-gw/main.cc | 7 +++++-- srsepc/src/mbms-gw/mbms-gw.cc | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/srsepc/hdr/mbms-gw/mbms-gw.h b/srsepc/hdr/mbms-gw/mbms-gw.h index 2beca7dcb..c238c0a18 100644 --- a/srsepc/hdr/mbms-gw/mbms-gw.h +++ b/srsepc/hdr/mbms-gw/mbms-gw.h @@ -49,6 +49,7 @@ const uint16_t GTPU_RX_PORT = 2152; typedef struct { std::string name; std::string sgi_mb_if_addr; + std::string sgi_mb_if_mask; std::string m1u_multi_addr; } mbms_gw_args_t; diff --git a/srsepc/mbms.conf.example b/srsepc/mbms.conf.example index 393be7648..d92306328 100644 --- a/srsepc/mbms.conf.example +++ b/srsepc/mbms.conf.example @@ -12,7 +12,8 @@ ##################################################################### [mbms_gw] name = srsmbmsgw01 -sgi_mb_if_addr = 172.16.1.1 +sgi_mb_if_addr = 172.16.0.254 +sgi_mb_if_mask = 255.255.255.255 m1u_multi_addr = 239.255.0.1 #################################################################### diff --git a/srsepc/src/mbms-gw/main.cc b/srsepc/src/mbms-gw/main.cc index a54f071c8..8aefc248d 100644 --- a/srsepc/src/mbms-gw/main.cc +++ b/srsepc/src/mbms-gw/main.cc @@ -99,8 +99,9 @@ parse_args(all_args_t *args, int argc, char* argv[]) { common.add_options() ("mbms_gw.name", bpo::value(&mbms_gw_name)->default_value("srsmbmsgw01"), "MBMS-GW Name") - ("mbms_gw.sgi_mb_if_addr", bpo::value(&mbms_gw_sgi_mb_if_addr)->default_value("172.16.1.1"), "SGi-mb TUN interface Address") - ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_m1u_multi_addr)->default_value("239.255.0.1"), "M1-u GTPu destination multicast address") + ("mbms_gw.sgi_mb_if_addr", bpo::value(&mbms_gw_sgi_mb_if_addr)->default_value("172.16.1.1"), "SGi-mb TUN interface Address.") + ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_sgi_mb_if_mask)->default_value("255.255.255.255"), "SGi-mb TUN interface mask.") + ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_m1u_multi_addr)->default_value("239.255.0.1"), "M1-u GTPu destination multicast address.") ("log.all_level", bpo::value(&args->log_args.all_level)->default_value("info"), "ALL log level") ("log.all_hex_limit", bpo::value(&args->log_args.all_hex_limit)->default_value(32), "ALL log hex dump limit") @@ -152,7 +153,9 @@ parse_args(all_args_t *args, int argc, char* argv[]) { args->mbms_gw_args.name = mbms_gw_name; args->mbms_gw_args.sgi_mb_if_addr = mbms_gw_sgi_mb_if_addr; + args->mbms_gw_args.sgi_mb_if_mask = mbms_gw_sgi_mb_if_mask; args->mbms_gw_args.m1u_multi_addr = mbms_gw_m1u_multi_addr; + // Apply all_level to any unset layers if (vm.count("log.all_level")) { if(!vm.count("log.mbms_gw_level")) { diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index e29b6629f..b373df4e7 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -196,7 +196,7 @@ mbms_gw::init_sgi_mb_if(mbms_gw_args_t *args) } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args->sgi_mb_if_mask.c_str()); if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) { m_mbms_gw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); close(m_sgi_mb_if); From 5a0de019058115f83b284b4f4d2a7098ced07d93 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Jul 2018 12:52:22 +0200 Subject: [PATCH 26/28] adding async thread to soapy --- lib/src/phy/rf/rf_soapy_imp.c | 69 ++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 359092d28..a0dcc6542 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -40,6 +40,8 @@ #include #include +#define HAVE_ASYNC_THREAD 1 + #define USE_TX_MTU 0 #define SET_RF_BW 1 @@ -64,6 +66,9 @@ typedef struct { srslte_rf_error_handler_t soapy_error_handler; + bool async_thread_running; + pthread_t async_thread; + uint32_t num_time_errors; uint32_t num_lates; uint32_t num_overflows; @@ -111,6 +116,41 @@ static void log_underflow(rf_soapy_handler_t *h) { } +#if HAVE_ASYNC_THREAD +static void* async_thread(void *h) { + rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + + while(handler->async_thread_running) { + int ret = 0; + size_t chanMask = 0; + int flags = 0; + const long timeoutUs = 400000; // arbitrarily chosen + long long timeNs; + + ret = SoapySDRDevice_readStreamStatus(handler->device, handler->txStream, &chanMask, &flags, &timeNs, timeoutUs); + if (ret == SOAPY_SDR_TIME_ERROR) { + // this is a late + log_late(handler, false); + } else if (ret == SOAPY_SDR_UNDERFLOW) { + log_underflow(handler); + } else if (ret == SOAPY_SDR_OVERFLOW) { + log_overflow(handler); + } else if (ret == SOAPY_SDR_TIMEOUT) { + // this is a timeout of the readStreamStatus call, ignoring it .. + } else if (ret == SOAPY_SDR_NOT_SUPPORTED) { + // stopping async thread + fprintf(stderr, "Receiving async metadata not supported by device. Exiting thread.\n"); + handler->async_thread_running = false; + } else { + fprintf(stderr, "Error while receiving aync metadata: %s (%d), flags=%d, channel=%zu, timeNs=%lld\n", SoapySDR_errToStr(ret), ret, flags, chanMask, timeNs); + handler->async_thread_running = false; + } + } + return NULL; +} +#endif + + int soapy_error(void *h) { return 0; @@ -397,6 +437,14 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) } } +#if HAVE_ASYNC_THREAD + bool start_async_thread = true; + if (strstr(args, "silent")) { + REMOVE_SUBSTRING_WITHCOMAS(args, "silent"); + start_async_thread = false; + } +#endif + // receive one subframe to allow for transceiver calibration if (strstr(devname, "lime")) { // set default tx gain and leave some time to calibrate tx @@ -434,6 +482,17 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_TX, 0); printf("Tx antenna set to %s\n", ant); +#if HAVE_ASYNC_THREAD + if (start_async_thread) { + // Start low priority thread to receive async commands + handler->async_thread_running = true; + if (pthread_create(&handler->async_thread, NULL, async_thread, handler)) { + perror("pthread_create"); + return -1; + } + } +#endif + return SRSLTE_SUCCESS; } @@ -447,6 +506,14 @@ int rf_soapy_open(char *args, void **h) int rf_soapy_close(void *h) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + +#if HAVE_ASYNC_THREAD + if (handler->async_thread_running) { + handler->async_thread_running = false; + pthread_join(handler->async_thread, NULL); + } +#endif + if (handler->tx_stream_active) { rf_soapy_stop_tx_stream(handler); SoapySDRDevice_closeStream(handler->device, handler->txStream); @@ -456,7 +523,7 @@ int rf_soapy_close(void *h) rf_soapy_stop_rx_stream(handler); SoapySDRDevice_closeStream(handler->device, handler->rxStream); } - + SoapySDRDevice_unmake(handler->device); free(handler); From 712a1b763912343a40607f001e596c476e93ae1c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 6 Jul 2018 12:13:44 +0100 Subject: [PATCH 27/28] Fix compiling bug --- srsepc/src/mbms-gw/main.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsepc/src/mbms-gw/main.cc b/srsepc/src/mbms-gw/main.cc index 8aefc248d..f99568246 100644 --- a/srsepc/src/mbms-gw/main.cc +++ b/srsepc/src/mbms-gw/main.cc @@ -83,6 +83,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mbms_gw_name; string mbms_gw_sgi_mb_if_addr; + string mbms_gw_sgi_mb_if_mask; string mbms_gw_m1u_multi_addr; string log_filename; From a74d1905b46110d8998f9bfa9e116af64968e875 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 6 Jul 2018 12:23:36 +0100 Subject: [PATCH 28/28] Fix command line parsing in mbms-gw --- srsepc/src/mbms-gw/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/mbms-gw/main.cc b/srsepc/src/mbms-gw/main.cc index f99568246..f99356071 100644 --- a/srsepc/src/mbms-gw/main.cc +++ b/srsepc/src/mbms-gw/main.cc @@ -101,7 +101,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mbms_gw.name", bpo::value(&mbms_gw_name)->default_value("srsmbmsgw01"), "MBMS-GW Name") ("mbms_gw.sgi_mb_if_addr", bpo::value(&mbms_gw_sgi_mb_if_addr)->default_value("172.16.1.1"), "SGi-mb TUN interface Address.") - ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_sgi_mb_if_mask)->default_value("255.255.255.255"), "SGi-mb TUN interface mask.") + ("mbms_gw.sgi_mb_if_mask", bpo::value(&mbms_gw_sgi_mb_if_mask)->default_value("255.255.255.255"), "SGi-mb TUN interface mask.") ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_m1u_multi_addr)->default_value("239.255.0.1"), "M1-u GTPu destination multicast address.") ("log.all_level", bpo::value(&args->log_args.all_level)->default_value("info"), "ALL log level")