adding common code including headers and tests

This commit is contained in:
Andre Puschmann 2017-05-18 12:11:31 +02:00
parent eb0e104bb2
commit ae186d8195
49 changed files with 7477 additions and 0 deletions

View File

@ -0,0 +1,118 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef BCD_HELPERS
#define BCD_HELPERS
#include <ctype.h>
#include <stdint.h>
#include <string>
namespace srslte {
/******************************************************************************
* Convert between string and BCD-coded MCC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.
* MCC 001 results in 0xF001
*****************************************************************************/
inline bool string_to_mcc(std::string str, uint16_t *mcc)
{
uint32_t len = str.size();
if(len != 3) {
return false;
}
if(!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2])) {
return false;
}
*mcc = 0xF000;
*mcc |= ((uint8_t)(str[0]-'0') << 8);
*mcc |= ((uint8_t)(str[1]-'0') << 4);
*mcc |= ((uint8_t)(str[2]-'0'));
return true;
}
inline bool mcc_to_string(uint16_t mcc, std::string *str)
{
if((mcc & 0xF000) != 0xF000) {
return false;
}
*str = "";
*str += ((mcc & 0x0F00) >> 8) + '0';
*str += ((mcc & 0x00F0) >> 4) + '0';
*str += (mcc & 0x000F) + '0';
return true;
}
/******************************************************************************
* Convert between string and BCD-coded MNC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.
* MNC 001 results in 0xF001
* MNC 01 results in 0xFF01
*****************************************************************************/
inline bool string_to_mnc(std::string str, uint16_t *mnc)
{
uint32_t len = str.size();
if(len != 3 && len != 2) {
return false;
}
if(len == 3) {
if(!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2])) {
return false;
}
*mnc = 0xF000;
*mnc |= ((uint8_t)(str[0]-'0') << 8);
*mnc |= ((uint8_t)(str[1]-'0') << 4);
*mnc |= ((uint8_t)(str[2]-'0'));
}
if(len == 2) {
if(!isdigit(str[0]) || !isdigit(str[1])) {
return false;
}
*mnc = 0xFF00;
*mnc |= ((uint8_t)(str[0]-'0') << 4);
*mnc |= ((uint8_t)(str[1]-'0'));
}
return true;
}
inline bool mnc_to_string(uint16_t mnc, std::string *str)
{
if((mnc & 0xF000) != 0xF000) {
return false;
}
*str = "";
if((mnc & 0xFF00) != 0xFF00) {
*str += ((mnc & 0x0F00) >> 8) + '0';
}
*str += ((mnc & 0x00F0) >> 4) + '0';
*str += (mnc & 0x000F) + '0';
return true;
}
} // namespace srslte
#endif // BCD_HELPERS

View File

@ -0,0 +1,97 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef BLOCK_QUEUE
#define BLOCK_QUEUE
#include <queue>
#include <memory>
#include <utility>
#include <pthread.h>
#include <stdio.h>
namespace srslte {
template<typename myobj>
class block_queue {
public:
block_queue<myobj>() {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cvar, NULL);
}
void push(const myobj& value) {
pthread_mutex_lock(&mutex);
q.push(value);
pthread_cond_signal(&cvar);
pthread_mutex_unlock(&mutex);
}
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();
}
pthread_mutex_unlock(&mutex);
return true;
}
myobj wait_pop() { // blocking pop
pthread_mutex_lock(&mutex);
while(q.empty()) {
pthread_cond_wait(&cvar, &mutex);
}
myobj value = q.front();
q.pop();
pthread_mutex_unlock(&mutex);
return value;
}
bool empty() const { // queue is empty?
pthread_mutex_lock(&mutex);
bool ret = q.empty();
pthread_mutex_unlock(&mutex);
return ret;
}
void clear() { // remove all items
myobj item;
while (try_pop(item));
}
private:
std::queue<myobj> q;
pthread_mutex_t mutex;
pthread_cond_t cvar;
};
}
#endif

View File

@ -0,0 +1,151 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef BUFFER_POOL_H
#define BUFFER_POOL_H
#include <pthread.h>
#include <vector>
#include <stack>
#include <algorithm>
/*******************************************************************************
INCLUDES
*******************************************************************************/
#include "common/common.h"
namespace srslte {
/******************************************************************************
* Buffer pool
*
* Preallocates a large number of buffer_t and provides allocate and
* deallocate functions. Provides quick object creation and deletion as well
* as object reuse.
* Singleton class of byte_buffer_t (but other pools of different type can be created)
*****************************************************************************/
template <class buffer_t>
class buffer_pool{
public:
// non-static methods
buffer_pool(uint32_t nof_buffers = POOL_SIZE)
{
pthread_mutex_init(&mutex, NULL);
for(int i=0;i<nof_buffers;i++) {
buffer_t *b = new buffer_t;
available.push(b);
}
capacity = nof_buffers;
}
~buffer_pool() {
// this destructor assumes all buffers have been properly deallocated
while(available.size()) {
delete available.top();
available.pop();
}
}
buffer_t* allocate()
{
pthread_mutex_lock(&mutex);
buffer_t* b = NULL;
if(available.size() > 0)
{
b = available.top();
used.push_back(b);
available.pop();
if (available.size() < capacity/20) {
printf("Warning buffer pool capacity is %f %%\n", (float) available.size()/capacity);
}
} else {
printf("Error - buffer pool is empty\n");
}
pthread_mutex_unlock(&mutex);
return b;
}
bool deallocate(buffer_t *b)
{
bool ret = false;
pthread_mutex_lock(&mutex);
typename std::vector<buffer_t*>::iterator elem = std::find(used.begin(), used.end(), b);
if (elem != used.end()) {
used.erase(elem);
available.push(b);
ret = true;
} else {
printf("Error deallocating from buffer pool: buffer not created in this pool.\n");
}
pthread_mutex_unlock(&mutex);
return ret;
}
private:
static const int POOL_SIZE = 2048;
std::stack<buffer_t*> available;
std::vector<buffer_t*> used;
pthread_mutex_t mutex;
uint32_t capacity;
};
class byte_buffer_pool {
public:
// Singleton static methods
static byte_buffer_pool *instance;
static byte_buffer_pool* get_instance(void);
static void cleanup(void);
byte_buffer_pool() {
pool = new buffer_pool<byte_buffer_t>;
}
~byte_buffer_pool() {
delete pool;
}
byte_buffer_t* allocate() {
return pool->allocate();
}
void deallocate(byte_buffer_t *b) {
b->reset();
pool->deallocate(b);
}
private:
buffer_pool<byte_buffer_t> *pool;
};
} // namespace srsue
#endif // BUFFER_POOL_H

View File

@ -0,0 +1,224 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef COMMON_H
#define COMMON_H
/*******************************************************************************
INCLUDES
*******************************************************************************/
#include <stdint.h>
#include <string.h>
/*******************************************************************************
DEFINES
*******************************************************************************/
#define SRSUE_UE_CATEGORY 4
#define SRSUE_N_SRB 3
#define SRSUE_N_DRB 8
#define SRSUE_N_RADIO_BEARERS 11
// Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI
// 3GPP 36.306 Table 4.1.1
#define SRSUE_MAX_BUFFER_SIZE_BITS 102048
#define SRSUE_MAX_BUFFER_SIZE_BYTES 12756
#define SRSUE_BUFFER_HEADER_OFFSET 1024
#include "srslte/srslte.h"
/*******************************************************************************
TYPEDEFS
*******************************************************************************/
namespace srslte {
typedef enum{
ERROR_NONE = 0,
ERROR_INVALID_PARAMS,
ERROR_INVALID_COMMAND,
ERROR_OUT_OF_BOUNDS,
ERROR_CANT_START,
ERROR_ALREADY_STARTED,
ERROR_N_ITEMS,
}error_t;
static const char error_text[ERROR_N_ITEMS][20] = { "None",
"Invalid parameters",
"Invalid command",
"Out of bounds",
"Can't start",
"Already started"};
typedef enum{
RB_ID_SRB0 = 0,
RB_ID_SRB1,
RB_ID_SRB2,
RB_ID_DRB1,
RB_ID_DRB2,
RB_ID_DRB3,
RB_ID_DRB4,
RB_ID_DRB5,
RB_ID_DRB6,
RB_ID_DRB7,
RB_ID_DRB8,
RB_ID_N_ITEMS,
}rb_id_t;
static const char rb_id_text[RB_ID_N_ITEMS][20] = { "SRB0",
"SRB1",
"SRB2",
"DRB1",
"DRB2",
"DRB3",
"DRB4",
"DRB5",
"DRB6",
"DRB7",
"DRB8"};
/******************************************************************************
* Byte and Bit buffers
*
* Generic buffers with headroom to accommodate packet headers and custom
* copy constructors & assignment operators for quick copying. Byte buffer
* holds a next pointer to support linked lists.
*****************************************************************************/
class byte_buffer_t{
public:
uint32_t N_bytes;
uint8_t buffer[SRSUE_MAX_BUFFER_SIZE_BYTES];
uint8_t *msg;
byte_buffer_t():N_bytes(0)
{
timestamp_is_set = false;
msg = &buffer[SRSUE_BUFFER_HEADER_OFFSET];
next = NULL;
}
byte_buffer_t(const byte_buffer_t& buf)
{
N_bytes = buf.N_bytes;
memcpy(msg, buf.msg, N_bytes);
}
byte_buffer_t & operator= (const byte_buffer_t & buf)
{
N_bytes = buf.N_bytes;
memcpy(msg, buf.msg, N_bytes);
}
void reset()
{
msg = &buffer[SRSUE_BUFFER_HEADER_OFFSET];
N_bytes = 0;
timestamp_is_set = false;
}
uint32_t get_headroom()
{
return msg-buffer;
}
long get_latency_us()
{
if(!timestamp_is_set)
return 0;
gettimeofday(&timestamp[2], NULL);
get_time_interval(timestamp);
return timestamp[0].tv_usec;
}
void set_timestamp()
{
gettimeofday(&timestamp[1], NULL);
timestamp_is_set = true;
}
private:
void get_time_interval(struct timeval * tdata) {
tdata[0].tv_sec = tdata[2].tv_sec - tdata[1].tv_sec;
tdata[0].tv_usec = tdata[2].tv_usec - tdata[1].tv_usec;
if (tdata[0].tv_usec < 0) {
tdata[0].tv_sec--;
tdata[0].tv_usec += 1000000;
}
}
struct timeval timestamp[3];
bool timestamp_is_set;
byte_buffer_t *next;
};
struct bit_buffer_t{
uint32_t N_bits;
uint8_t buffer[SRSUE_MAX_BUFFER_SIZE_BITS];
uint8_t *msg;
bit_buffer_t():N_bits(0)
{
msg = &buffer[SRSUE_BUFFER_HEADER_OFFSET];
}
bit_buffer_t(const bit_buffer_t& buf){
N_bits = buf.N_bits;
memcpy(msg, buf.msg, N_bits);
}
bit_buffer_t & operator= (const bit_buffer_t & buf){
N_bits = buf.N_bits;
memcpy(msg, buf.msg, N_bits);
}
void reset()
{
msg = &buffer[SRSUE_BUFFER_HEADER_OFFSET];
N_bits = 0;
timestamp_is_set = false;
}
uint32_t get_headroom()
{
return msg-buffer;
}
long get_latency_us()
{
if(!timestamp_is_set)
return 0;
gettimeofday(&timestamp[2], NULL);
return timestamp[0].tv_usec;
}
void set_timestamp()
{
gettimeofday(&timestamp[1], NULL);
timestamp_is_set = true;
}
private:
struct timeval timestamp[3];
bool timestamp_is_set;
};
} // namespace srsue
#endif // COMMON_H

View File

@ -0,0 +1,57 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef CONFIG_H
#define CONFIG_H
// Generic helper definitions for shared library support
#if defined _WIN32 || defined __CYGWIN__
#define SRSAPPS_IMPORT __declspec(dllimport)
#define SRSAPPS_EXPORT __declspec(dllexport)
#define SRSAPPS_LOCAL
#else
#if __GNUC__ >= 4
#define SRSAPPS_IMPORT __attribute__ ((visibility ("default")))
#define SRSAPPS_EXPORT __attribute__ ((visibility ("default")))
#else
#define SRSAPPS_IMPORT
#define SRSAPPS_EXPORT
#define SRSAPPS_LOCAL
#endif
#endif
// Define SRSAPPS_API
// is used for the public API symbols.
#ifdef SRSAPPS_DLL_EXPORTS // defined if we are building the SRSAPPS DLL (instead of using it)
#define SRSAPPS_EXPORT
#else
#define SRSAPPS_IMPORT
#endif
// cf_t definition
typedef _Complex float cf_t;
#endif // CONFIG_H

View File

@ -0,0 +1,234 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: interfaces.h
* Description: Abstract base class interfaces provided by layers
* to other layers.
*****************************************************************************/
#ifndef INTERFACES_H
#define INTERFACES_H
#include "liblte_rrc.h"
#include "common/interfaces_common.h"
#include "common/common.h"
#include "common/security.h"
#include "mac_interface.h"
#include "phy_interface.h"
namespace srsue {
// UE interface
class ue_interface
{
};
// USIM interface for NAS
class usim_interface_nas
{
public:
virtual void get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
virtual void get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
virtual void generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res) = 0;
virtual void generate_nas_keys(uint8_t *k_nas_enc,
uint8_t *k_nas_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
};
// USIM interface for RRC
class usim_interface_rrc
{
public:
virtual void generate_as_keys(uint32_t count_ul,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
uint8_t *k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
};
// GW interface for NAS
class gw_interface_nas
{
public:
virtual srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str) = 0;
};
// GW interface for PDCP
class gw_interface_pdcp
{
public:
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
};
// NAS interface for RRC
class nas_interface_rrc
{
public:
virtual bool is_attached() = 0;
virtual void notify_connection_setup() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
};
// RRC interface for MAC
class rrc_interface_mac
{
public:
virtual void release_pucch_srs() = 0;
virtual void ra_problem() = 0;
};
// RRC interface for PHY
class rrc_interface_phy
{
public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
};
// RRC interface for NAS
class rrc_interface_nas
{
public:
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0;
};
// RRC interface for GW
class rrc_interface_gw
{
public:
virtual bool rrc_connected() = 0;
virtual void rrc_connect() = 0;
virtual bool have_drb() = 0;
};
// RRC interface for PDCP
class rrc_interface_pdcp
{
public:
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_pcch(srslte::byte_buffer_t *pdu) = 0;
};
// RRC interface for RLC
class rrc_interface_rlc
{
public:
virtual void max_retx_attempted() = 0;
};
// PDCP interface for GW
class pdcp_interface_gw
{
public:
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
};
// PDCP interface for RRC
class pdcp_interface_rrc
{
public:
virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL) = 0;
virtual void config_security(uint32_t lcid,
uint8_t *k_rrc_enc_,
uint8_t *k_rrc_int_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
};
// PDCP interface for RLC
class pdcp_interface_rlc
{
public:
/* RLC calls PDCP to push a PDCP PDU. */
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *sdu) = 0;
virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *sdu) = 0;
virtual void write_pdu_pcch(srslte::byte_buffer_t *sdu) = 0;
};
// RLC interface for RRC
class rlc_interface_rrc
{
public:
virtual void reset() = 0;
virtual void add_bearer(uint32_t lcid) = 0;
virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0;
};
// RLC interface for PDCP
class rlc_interface_pdcp
{
public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
};
//RLC interface for MAC
class rlc_interface_mac : public srslte::read_pdu_interface
{
public:
/* MAC calls RLC to get buffer state for a logical channel.
* This function should return quickly. */
virtual uint32_t get_buffer_state(uint32_t lcid) = 0;
virtual uint32_t get_total_buffer_state(uint32_t lcid) = 0;
const static int MAX_PDU_SEGMENTS = 20;
/* MAC calls RLC to get RLC segment of nof_bytes length.
* Segmentation happens in this function. RLC PDU is stored in payload. */
virtual int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread.
* PDU gets placed into the buffer and higher layer thread gets notified. */
virtual void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) = 0;
};
} // namespace srsue
#endif // INTERFACES_H

View File

@ -0,0 +1,27 @@
#include "common/timers.h"
#ifndef INTERFACE_COMMON_H
#define INTERFACE_COMMON_H
namespace srslte {
class mac_interface_timers
{
public:
/* Timer services with ms resolution.
* timer_id must be lower than MAC_NOF_UPPER_TIMERS
*/
virtual timers::timer* get(uint32_t timer_id) = 0;
virtual uint32_t get_unique_id() = 0;
};
class read_pdu_interface
{
public:
virtual int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t requested_bytes) = 0;
};
}
#endif

View File

@ -0,0 +1,127 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: log.h
*
* Description: Abstract logging service
*
* Reference:
*****************************************************************************/
#ifndef LOG_H
#define LOG_H
#include <stdint.h>
#include <string>
namespace srslte {
typedef enum {
LOG_LEVEL_NONE = 0,
LOG_LEVEL_ERROR,
LOG_LEVEL_WARNING,
LOG_LEVEL_INFO,
LOG_LEVEL_DEBUG,
LOG_LEVEL_N_ITEMS
} LOG_LEVEL_ENUM;
static const char log_level_text[LOG_LEVEL_N_ITEMS][16] = {"None ",
"Error ",
"Warning",
"Info ",
"Debug "};
class log
{
public:
log() {
service_name = "";
tti = 0;
level = LOG_LEVEL_NONE;
hex_limit = 0;
}
log(std::string service_name_) {
service_name = service_name_;
tti = 0;
level = LOG_LEVEL_NONE;
hex_limit = 0;
}
// This function shall be called at the start of every tti for printing tti
void step(uint32_t tti_) {
tti = tti_;
}
uint32_t get_tti() {
return tti;
}
void set_level(LOG_LEVEL_ENUM l) {
level = l;
}
LOG_LEVEL_ENUM get_level() {
return level;
}
void set_hex_limit(int limit) {
hex_limit = limit;
}
int get_hex_limit() {
return hex_limit;
}
// Pure virtual methods for logging
virtual void console(std::string message, ...) = 0;
virtual void error(std::string message, ...) = 0;
virtual void warning(std::string message, ...) = 0;
virtual void info(std::string message, ...) = 0;
virtual void debug(std::string message, ...) = 0;
// Same with hex dump
virtual void error_hex(uint8_t *hex, int size, std::string message, ...){error("error_hex not implemented.\n");}
virtual void warning_hex(uint8_t *hex, int size, std::string message, ...){error("warning_hex not implemented.\n");}
virtual void info_hex(uint8_t *hex, int size, std::string message, ...){error("info_hex not implemented.\n");}
virtual void debug_hex(uint8_t *hex, int size, std::string message, ...){error("debug_hex not implemented.\n");}
// Same with line and file info
virtual void error_line(std::string file, int line, std::string message, ...){error("error_line not implemented.\n");}
virtual void warning_line(std::string file, int line, std::string message, ...){error("warning_line not implemented.\n");}
virtual void info_line(std::string file, int line, std::string message, ...){error("info_line not implemented.\n");}
virtual void debug_line(std::string file, int line, std::string message, ...){error("debug_line not implemented.\n");}
protected:
std::string get_service_name() { return service_name; }
uint32_t tti;
LOG_LEVEL_ENUM level;
int hex_limit;
std::string service_name;
};
} // namespace srslte
#endif // LOG_H

View File

@ -0,0 +1,83 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: log_filter.h
* Description: Log filter for a specific layer or element.
* Performs filtering based on log level, generates
* timestamped log strings and passes them to the
* common logger object.
*****************************************************************************/
#ifndef LOG_FILTER_H
#define LOG_FILTER_H
#include <stdarg.h>
#include <string>
#include <common/log.h>
#include "logger.h"
namespace srslte {
class log_filter : public srslte::log
{
public:
log_filter();
log_filter(std::string layer, logger *logger_, bool tti=false);
void init(std::string layer, logger *logger_, bool tti=false);
void console(std::string message, ...);
void error(std::string message, ...);
void warning(std::string message, ...);
void info(std::string message, ...);
void debug(std::string message, ...);
void error_hex(uint8_t *hex, int size, std::string message, ...);
void warning_hex(uint8_t *hex, int size, std::string message, ...);
void info_hex(uint8_t *hex, int size, std::string message, ...);
void debug_hex(uint8_t *hex, int size, std::string message, ...);
void error_line(std::string file, int line, std::string message, ...);
void warning_line(std::string file, int line, std::string message, ...);
void info_line(std::string file, int line, std::string message, ...);
void debug_line(std::string file, int line, std::string message, ...);
private:
logger *logger_h;
bool do_tti;
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg, uint8_t *hex, int size);
void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg);
std::string now_time();
std::string hex_string(uint8_t *hex, int size);
};
} // namespace srsue
#endif // LOG_FILTER_H

View File

@ -0,0 +1,82 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: log_stout.h
*
* Description: Logging service through standard output. Inherits log interface
*
* Reference:
*****************************************************************************/
#ifndef LOGSTDOUT_H
#define LOGSTDOUT_H
#include <stdarg.h>
#include <string>
#include <common/log.h>
namespace srslte {
class log_stdout : public log
{
public:
log_stdout(std::string service_name_) : log(service_name_) { }
void console(std::string message, ...);
void error(std::string message, ...);
void warning(std::string message, ...);
void info(std::string message, ...);
void debug(std::string message, ...);
// Same with hex dump
void error_hex(uint8_t *hex, int size, std::string message, ...);
void warning_hex(uint8_t *hex, int size, std::string message, ...);
void info_hex(uint8_t *hex, int size, std::string message, ...);
void debug_hex(uint8_t *hex, int size, std::string message, ...);
// Same with line and file info
void error_line(std::string file, int line, std::string message, ...);
void warning_line(std::string file, int line, std::string message, ...);
void info_line(std::string file, int line, std::string message, ...);
void debug_line(std::string file, int line, std::string message, ...);
private:
void printlog(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, std::string message, va_list args);
void printlog(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string message, va_list args);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg, uint8_t *hex, int size);
void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg);
std::string now_time();
std::string hex_string(uint8_t *hex, int size);
};
}
#endif

View File

@ -0,0 +1,74 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: logger.h
* Description: Common log object. Maintains a queue of log messages
* and runs a thread to read messages and write to file.
* Multiple producers, single consumer. If full, producers
* increase queue size. If empty, consumer blocks.
*****************************************************************************/
#ifndef LOGGER_H
#define LOGGER_H
#include <stdio.h>
#include <deque>
#include <string>
#include "common/threads.h"
namespace srslte {
typedef std::string* str_ptr;
class logger : public thread
{
public:
logger();
logger(std::string file);
~logger();
void init(std::string file);
void log(const char *msg);
void log(str_ptr msg);
private:
void run_thread();
void flush();
FILE* logfile;
bool inited;
bool not_done;
std::string filename;
pthread_cond_t not_empty;
pthread_cond_t not_full;
pthread_mutex_t mutex;
pthread_t thread;
std::deque<str_ptr> buffer;
};
} // namespace srsue
#endif // LOGGER_H

View File

@ -0,0 +1,177 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: mac_interface.h
* Description: LTE MAC layer interface
* Reference:
*****************************************************************************/
#ifndef MAC_INTERFACE_H
#define MAC_INTERFACE_H
#include <stdint.h>
#include <string>
#include "srslte/srslte.h"
#include "common/interfaces_common.h"
#include "common/timers.h"
#include "liblte_rrc.h"
namespace srsue {
/* Interface PHY -> MAC */
class mac_interface_phy
{
public:
typedef struct {
uint32_t pid;
uint32_t tti;
uint32_t last_tti;
bool ndi;
bool last_ndi;
uint32_t n_bytes;
int rv;
uint16_t rnti;
bool is_from_rar;
bool is_sps_release;
bool has_cqi_request;
srslte_rnti_type_t rnti_type;
srslte_phy_grant_t phy_grant;
} mac_grant_t;
typedef struct {
bool decode_enabled;
int rv;
uint16_t rnti;
bool generate_ack;
bool default_ack;
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent
bool (*generate_ack_callback)(void*);
void *generate_ack_callback_arg;
uint8_t *payload_ptr;
srslte_softbuffer_rx_t *softbuffer;
srslte_phy_grant_t phy_grant;
} tb_action_dl_t;
typedef struct {
bool tx_enabled;
bool expect_ack;
uint32_t rv;
uint16_t rnti;
uint32_t current_tx_nb;
srslte_softbuffer_tx_t *softbuffer;
srslte_phy_grant_t phy_grant;
uint8_t *payload_ptr;
} tb_action_ul_t;
/* Indicate reception of UL grant.
* payload_ptr points to memory where MAC PDU must be written by MAC layer */
virtual void new_grant_ul(mac_grant_t grant, tb_action_ul_t *action) = 0;
/* Indicate reception of UL grant + HARQ information throught PHICH in the same TTI. */
virtual void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action) = 0;
/* Indicate reception of HARQ information only through PHICH. */
virtual void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action) = 0;
/* Indicate reception of DL grant. */
virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0;
/* Indicate successfull decoding of PDSCH TB. */
virtual void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0;
/* Indicate successfull decoding of BCH TB through PBCH */
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;
/* Indicate successfull decoding of PCH TB through PDSCH */
virtual void pch_decoded_ok(uint32_t len) = 0;
/* Function called every start of a subframe (TTI). Warning, this function is called
* from a high priority thread and should terminate asap
*/
virtual void tti_clock(uint32_t tti) = 0;
};
/* Interface RRC -> MAC */
class mac_interface_rrc
{
public:
typedef struct {
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main;
LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach;
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr;
uint32_t prach_config_index;
} mac_cfg_t;
// Class to handle UE specific RNTIs between RRC and MAC
typedef struct {
uint16_t crnti;
uint16_t temp_rnti;
uint16_t tpc_rnti;
uint16_t sps_rnti;
uint64_t contention_id;
} ue_rnti_t;
/* Instructs the MAC to start receiving BCCH */
virtual void bcch_start_rx() = 0;
virtual void bcch_stop_rx() = 0;
virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0;
/* Instructs the MAC to start receiving PCCH */
virtual void pcch_start_rx() = 0;
virtual void pcch_stop_rx() = 0;
/* RRC configures a logical channel */
virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0;
virtual uint32_t get_current_tti() = 0;
virtual void set_config(mac_cfg_t *mac_cfg) = 0;
virtual void set_config_main(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *main_cfg) = 0;
virtual void set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cfg, uint32_t prach_config_index) = 0;
virtual void set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sr_cfg) = 0;
virtual void get_config(mac_cfg_t *mac_cfg) = 0;
virtual void get_rntis(ue_rnti_t *rntis) = 0;
virtual void set_contention_id(uint64_t uecri) = 0;
virtual void reconfiguration() = 0;
virtual void reset() = 0;
};
}
#endif

View File

@ -0,0 +1,61 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef MACPCAP_H
#define MACPCAP_H
#include <stdint.h>
#include "common/pcap.h"
namespace srslte {
class mac_pcap
{
public:
mac_pcap() {enable_write=false; ue_id=0; pcap_file = NULL; };
void enable(bool en);
void open(const char *filename, uint32_t ue_id = 0);
void close();
void write_ul_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti);
void write_dl_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti);
void write_dl_ranti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti);
// SI and BCH only for DL
void write_dl_sirnti(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti);
void write_dl_bch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti);
void write_dl_pch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti);
private:
bool enable_write;
FILE *pcap_file;
uint32_t ue_id;
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
uint16_t crnti_, uint8_t direction, uint8_t rnti_type);
};
} // namespace srsue
#endif // MACPCAP_H

View File

@ -0,0 +1,61 @@
/******************************************************************************
* File: metrics_hub.h
* Description: Centralizes metrics interfaces to allow different metrics clients
* to get metrics
*****************************************************************************/
#ifndef METRICS_HUB_H
#define METRICS_HUB_H
#include <vector>
#include "common/threads.h"
namespace srslte {
template<typename metrics_t>
class metrics_interface
{
public:
virtual bool get_metrics(metrics_t &m) = 0;
};
template<typename metrics_t>
class metrics_listener
{
public:
virtual void set_metrics(metrics_t &m) = 0;
};
template<typename metrics_t>
class metrics_hub : public periodic_thread
{
public:
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
m = m_;
start_periodic(report_period_secs*1e6);
}
void stop() {
thread_cancel();
}
void add_listener(metrics_listener<metrics_t> *listener) {
listeners.push_back(listener);
}
private:
void run_period() {
metrics_t metric;
m->get_metrics(metric);
for (int i=0;i<listeners.size();i++) {
listeners[i]->set_metrics(metric);
}
}
metrics_interface<metrics_t> *m;
std::vector<metrics_listener<metrics_t>*> listeners;
};
} // namespace srslte
#endif // METRICS_HUB_H

View File

@ -0,0 +1,152 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: msg_queue.h
* Description: Thread-safe bounded circular buffer of srsue_byte_buffer pointers.
* Reference:
*****************************************************************************/
#ifndef MSG_QUEUE_H
#define MSG_QUEUE_H
#include "common/common.h"
#include <pthread.h>
namespace srslte {
class msg_queue
{
public:
msg_queue(uint32_t capacity_ = 128)
:head(0)
,tail(0)
,unread(0)
,unread_bytes(0)
,capacity(capacity_)
{
buf = new byte_buffer_t*[capacity];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&not_empty, NULL);
pthread_cond_init(&not_full, NULL);
}
~msg_queue()
{
delete [] buf;
}
void write(byte_buffer_t *msg)
{
pthread_mutex_lock(&mutex);
while(is_full()) {
pthread_cond_wait(&not_full, &mutex);
}
buf[head] = msg;
head = (head+1)%capacity;
unread++;
unread_bytes += msg->N_bytes;
pthread_cond_signal(&not_empty);
pthread_mutex_unlock(&mutex);
}
void read(byte_buffer_t **msg)
{
pthread_mutex_lock(&mutex);
while(is_empty()) {
pthread_cond_wait(&not_empty, &mutex);
}
*msg = buf[tail];
tail = (tail+1)%capacity;
unread--;
unread_bytes -= (*msg)->N_bytes;
pthread_cond_signal(&not_full);
pthread_mutex_unlock(&mutex);
}
bool try_read(byte_buffer_t **msg)
{
pthread_mutex_lock(&mutex);
if(is_empty())
{
pthread_mutex_unlock(&mutex);
return false;
}else{
*msg = buf[tail];
tail = (tail+1)%capacity;
unread--;
unread_bytes -= (*msg)->N_bytes;
pthread_cond_signal(&not_full);
pthread_mutex_unlock(&mutex);
return true;
}
}
uint32_t size()
{
pthread_mutex_lock(&mutex);
uint32_t r = unread;
pthread_mutex_unlock(&mutex);
return r;
}
uint32_t size_bytes()
{
pthread_mutex_lock(&mutex);
uint32_t r = unread_bytes;
pthread_mutex_unlock(&mutex);
return r;
}
uint32_t size_tail_bytes()
{
pthread_mutex_lock(&mutex);
uint32_t r = buf[tail]->N_bytes;
pthread_mutex_unlock(&mutex);
return r;
}
private:
bool is_empty() const { return unread == 0; }
bool is_full() const { return unread == capacity; }
pthread_cond_t not_empty;
pthread_cond_t not_full;
pthread_mutex_t mutex;
byte_buffer_t **buf;
uint32_t capacity;
uint32_t unread;
uint32_t unread_bytes;
uint32_t head;
uint32_t tail;
};
} // namespace srsue
#endif // MSG_QUEUE_H

View File

@ -0,0 +1,218 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef UEPCAP_H
#define UEPCAP_H
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/time.h>
#define MAC_LTE_DLT 147
/* This structure gets written to the start of the file */
typedef struct pcap_hdr_s {
unsigned int magic_number; /* magic number */
unsigned short version_major; /* major version number */
unsigned short version_minor; /* minor version number */
unsigned int thiszone; /* GMT to local correction */
unsigned int sigfigs; /* accuracy of timestamps */
unsigned int snaplen; /* max length of captured packets, in octets */
unsigned int network; /* data link type */
} pcap_hdr_t;
/* This structure precedes each packet */
typedef struct pcaprec_hdr_s {
unsigned int ts_sec; /* timestamp seconds */
unsigned int ts_usec; /* timestamp microseconds */
unsigned int incl_len; /* number of octets of packet saved in file */
unsigned int orig_len; /* actual length of packet */
} pcaprec_hdr_t;
/* radioType */
#define FDD_RADIO 1
#define TDD_RADIO 2
/* Direction */
#define DIRECTION_UPLINK 0
#define DIRECTION_DOWNLINK 1
/* rntiType */
#define NO_RNTI 0 /* Used for BCH-BCH */
#define P_RNTI 1
#define RA_RNTI 2
#define C_RNTI 3
#define SI_RNTI 4
#define SPS_RNTI 5
#define M_RNTI 6
#define MAC_LTE_START_STRING "mac-lte"
#define MAC_LTE_RNTI_TAG 0x02
/* 2 bytes, network order */
#define MAC_LTE_UEID_TAG 0x03
/* 2 bytes, network order */
#define MAC_LTE_SUBFRAME_TAG 0x04
/* 2 bytes, network order */
#define MAC_LTE_PREDFINED_DATA_TAG 0x05
/* 1 byte */
#define MAC_LTE_RETX_TAG 0x06
/* 1 byte */
#define MAC_LTE_CRC_STATUS_TAG 0x07
/* 1 byte */
/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU
continues until the end of the frame) */
#define MAC_LTE_PAYLOAD_TAG 0x01
/* Context information for every MAC PDU that will be logged */
typedef struct MAC_Context_Info_t {
unsigned short radioType;
unsigned char direction;
unsigned char rntiType;
unsigned short rnti;
unsigned short ueid;
unsigned char isRetx;
unsigned char crcStatusOK;
unsigned short sysFrameNumber;
unsigned short subFrameNumber;
} MAC_Context_Info_t;
/**************************************************************************/
/* API functions for opening/writing/closing MAC-LTE PCAP files */
/* Open the file and write file header */
inline FILE *MAC_LTE_PCAP_Open(const char *fileName)
{
pcap_hdr_t file_header =
{
0xa1b2c3d4, /* magic number */
2, 4, /* version number is 2.4 */
0, /* timezone */
0, /* sigfigs - apparently all tools do this */
65535, /* snaplen - this should be long enough */
MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
};
FILE *fd = fopen(fileName, "w");
if (fd == NULL) {
printf("Failed to open file \"%s\" for writing\n", fileName);
return NULL;
}
/* Write the file header */
fwrite(&file_header, sizeof(pcap_hdr_t), 1, fd);
return fd;
}
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context,
const unsigned char *PDU, unsigned int length)
{
pcaprec_hdr_t packet_header;
char context_header[256];
int offset = 0;
unsigned short tmp16;
/* Can't write if file wasn't successfully opened */
if (fd == NULL) {
printf("Error: Can't write to empty file handle\n");
return 0;
}
/*****************************************************************/
/* Context information (same as written by UDP heuristic clients */
context_header[offset++] = context->radioType;
context_header[offset++] = context->direction;
context_header[offset++] = context->rntiType;
/* RNTI */
context_header[offset++] = MAC_LTE_RNTI_TAG;
tmp16 = htons(context->rnti);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* UEId */
context_header[offset++] = MAC_LTE_UEID_TAG;
tmp16 = htons(context->ueid);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* Subframe number */
context_header[offset++] = MAC_LTE_SUBFRAME_TAG;
tmp16 = htons(context->subFrameNumber);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* CRC Status */
context_header[offset++] = MAC_LTE_CRC_STATUS_TAG;
context_header[offset++] = context->crcStatusOK;
/* Data tag immediately preceding PDU */
context_header[offset++] = MAC_LTE_PAYLOAD_TAG;
/****************************************************************/
/* PCAP Header */
struct timeval t;
gettimeofday(&t, NULL);
packet_header.ts_sec = t.tv_sec;
packet_header.ts_usec = t.tv_usec;
packet_header.incl_len = offset + length;
packet_header.orig_len = offset + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd);
fwrite(context_header, 1, offset, fd);
fwrite(PDU, 1, length, fd);
return 1;
}
/* Close the PCAP file */
inline void MAC_LTE_PCAP_Close(FILE *fd)
{
if(fd)
fclose(fd);
}
#endif /* UEPCAP_H */

View File

@ -0,0 +1,339 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef MACPDU_H
#define MACPDU_H
#include <stdint.h>
#include "common/log.h"
#include "common/interfaces_common.h"
#include <vector>
#include <stdio.h>
/* MAC PDU Packing/Unpacking functions. Section 6 of 36.321 */
namespace srslte {
template<class SubH>
class pdu
{
public:
pdu(uint32_t max_subheaders_) : subheaders(max_subheaders_) {
max_subheaders = max_subheaders_;
nof_subheaders = 0;
cur_idx = -1;
pdu_len = 0;
rem_len = 0;
last_sdu_idx = -1;
pdu_is_ul = false;
buffer_tx = NULL;
total_sdu_len = 0;
}
void fprint(FILE *stream) {
fprintf(stream, "Number of Subheaders: %d\n", nof_subheaders);
for (int i=0;i<nof_subheaders;i++) {
fprintf(stream, " -- Subheader %d: ", i);
subheaders[i].fprint(stream);
}
}
/* Resets the Read/Write position and remaining PDU length */
void reset() {
cur_idx = -1;
last_sdu_idx = -1;
rem_len = pdu_len;
}
void init_rx(uint32_t pdu_len_bytes, bool is_ulsch = false) {
init_(NULL, pdu_len_bytes, is_ulsch);
}
void init_tx(uint8_t *payload, uint32_t pdu_len_bytes, bool is_ulsch = false) {
init_(payload, pdu_len_bytes, is_ulsch);
}
uint32_t nof_subh() {
return nof_subheaders;
}
bool new_subh() {
if (nof_subheaders < max_subheaders - 1 && rem_len > 0) {
nof_subheaders++;
next();
return true;
} else {
return false;
}
}
bool next() {
if (cur_idx < nof_subheaders - 1) {
cur_idx++;
return true;
} else {
return false;
}
}
void del_subh() {
if (nof_subheaders > 0) {
nof_subheaders--;
}
if (cur_idx > 0) {
cur_idx--;
}
}
SubH* get() {
if (cur_idx >= 0) {
return &subheaders[cur_idx];
} else {
return NULL;
}
}
bool is_ul() {
return pdu_is_ul;
}
uint8_t* get_current_sdu_ptr() {
return &buffer_tx[total_sdu_len+sdu_offset_start];
}
void add_sdu(uint32_t sdu_sz) {
total_sdu_len += sdu_sz;
}
// Section 6.1.2
void parse_packet(uint8_t *ptr) {
uint8_t *init_ptr = ptr;
nof_subheaders = 0;
while(subheaders[nof_subheaders].read_subheader(&ptr)) {
nof_subheaders++;
}
nof_subheaders++;
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].read_payload(&ptr);
}
}
protected:
std::vector<SubH> subheaders;
uint32_t pdu_len;
uint32_t rem_len;
int cur_idx;
int nof_subheaders;
uint32_t max_subheaders;
bool pdu_is_ul;
uint8_t* buffer_tx;
uint32_t total_sdu_len;
uint32_t sdu_offset_start;
int last_sdu_idx;
private:
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
void init_(uint8_t *buffer_tx_ptr, uint32_t pdu_len_bytes, bool is_ulsch) {
nof_subheaders = 0;
pdu_len = pdu_len_bytes;
rem_len = pdu_len;
pdu_is_ul = is_ulsch;
buffer_tx = buffer_tx_ptr;
sdu_offset_start = max_subheaders*2 + 13; // Assuming worst-case 2 bytes per sdu subheader + all possible CE
total_sdu_len = 0;
last_sdu_idx = -1;
reset();
for (int i=0;i<max_subheaders;i++) {
subheaders[i].parent = this;
subheaders[i].init();
}
}
};
template<class SubH>
class subh
{
public:
virtual bool read_subheader(uint8_t** ptr) = 0;
virtual void read_payload(uint8_t **ptr) = 0;
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
virtual void write_payload(uint8_t **ptr) = 0;
virtual void fprint(FILE *stream) = 0;
pdu<SubH>* parent;
private:
virtual void init() = 0;
};
class sch_subh : public subh<sch_subh>
{
public:
typedef enum {
PHR_REPORT = 26,
CRNTI = 27,
CON_RES_ID = 28,
TRUNC_BSR = 28,
TA_CMD = 29,
SHORT_BSR = 29,
DRX_CMD = 30,
LONG_BSR = 30,
PADDING = 31,
SDU = 0
} cetype;
// Size of MAC CEs
const static int MAC_CE_CONTRES_LEN = 6;
// Reading functions
bool is_sdu();
cetype ce_type();
uint32_t size_plus_header();
void set_payload_size(uint32_t size);
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t **ptr);
uint32_t get_sdu_lcid();
uint32_t get_payload_size();
uint32_t get_header_size(bool is_last);
uint8_t* get_sdu_ptr();
uint16_t get_c_rnti();
uint64_t get_con_res_id();
uint8_t get_ta_cmd();
float get_phr();
int get_bsr(uint32_t buff_size[4]);
// Writing functions
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t **ptr);
int set_sdu(uint32_t lcid, uint32_t nof_bytes, uint8_t *payload);
int set_sdu(uint32_t lcid, uint32_t requested_bytes, read_pdu_interface *sdu_itf);
bool set_c_rnti(uint16_t crnti);
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format);
bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd);
bool set_phr(float phr);
void set_padding();
void set_padding(uint32_t padding_len);
void init();
void fprint(FILE *stream);
private:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
int nof_bytes;
uint8_t* payload;
uint8_t w_payload_ce[8];
bool F_bit;
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
static uint8_t buff_size_table(uint32_t buffer_size);
static uint8_t phr_report_table(float phr_value);
};
class sch_pdu : public pdu<sch_subh>
{
public:
sch_pdu(uint32_t max_subh) : pdu(max_subh) {}
void parse_packet(uint8_t *ptr);
uint8_t* write_packet();
uint8_t* write_packet(srslte::log *log_h);
bool has_space_ce(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes);
int get_pdu_len();
int rem_size();
int get_sdu_space();
static uint32_t size_header_sdu(uint32_t nbytes);
bool update_space_ce(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes);
void fprint(FILE *stream);
};
class rar_subh : public subh<rar_subh>
{
public:
static const uint32_t RAR_GRANT_LEN = 20;
// Reading functions
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t** ptr);
uint32_t get_rapid();
uint32_t get_ta_cmd();
uint16_t get_temp_crnti();
void get_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
// Writing functoins
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t** ptr);
void set_rapid(uint32_t rapid);
void set_ta_cmd(uint32_t ta);
void set_temp_crnti(uint16_t temp_rnti);
void set_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
void init();
void fprint(FILE *stream);
private:
uint8_t grant[RAR_GRANT_LEN];
uint32_t ta;
uint16_t temp_rnti;
uint32_t preamble;
};
class rar_pdu : public pdu<rar_subh>
{
public:
rar_pdu(uint32_t max_rars = 16);
void set_backoff(uint8_t bi);
bool has_backoff();
uint8_t get_backoff();
bool write_packet(uint8_t* ptr);
void fprint(FILE *stream);
private:
bool has_backoff_indicator;
uint8_t backoff_indicator;
};
} // namespace srsue
#endif // MACPDU_H

View File

@ -0,0 +1,80 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef PDUPROC_H
#define PDUPROC_H
#include "common/log.h"
#include "common/block_queue.h"
#include "common/buffer_pool.h"
#include "common/timers.h"
#include "common/pdu.h"
/* Logical Channel Demultiplexing and MAC CE dissassemble */
namespace srslte {
class pdu_queue
{
public:
class process_callback
{
public:
virtual void process_pdu(uint8_t *buff, uint32_t len) = 0;
};
pdu_queue(uint32_t pool_size = DEFAULT_POOL_SIZE) : pool(pool_size), callback(NULL), log_h(NULL) {}
void init(process_callback *callback, log* log_h_);
uint8_t* request(uint32_t len);
void deallocate(uint8_t* pdu);
void push(uint8_t *ptr, uint32_t len);
bool process_pdus();
private:
const static int DEFAULT_POOL_SIZE = 64; // Number of PDU buffers in total
const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps
typedef struct {
uint8_t ptr[MAX_PDU_LEN];
uint32_t len;
} pdu_t;
block_queue<pdu_t*> pdu_q;
buffer_pool<pdu_t> pool;
process_callback *callback;
log *log_h;
};
} // namespace srslte
#endif // PDUPROC_H

View File

@ -0,0 +1,156 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: phy_interface.h
* Description: PHY layer interfaces provided to other layers
* Reference:
*****************************************************************************/
#ifndef PHY_INTERFACE_H
#define PHY_INTERFACE_H
#include <stdint.h>
#include <string>
#include "srslte/srslte.h"
#include "liblte_rrc.h"
namespace srsue {
typedef struct {
bool ul_pwr_ctrl_en;
float prach_gain;
int pdsch_max_its;
bool attach_enable_64qam;
int nof_phy_threads;
int worker_cpu_mask;
int sync_cpu_affinity;
uint32_t nof_rx_ant;
std::string equalizer_mode;
int cqi_max;
int cqi_fixed;
float snr_ema_coeff;
std::string snr_estim_alg;
bool cfo_integer_enabled;
float cfo_correct_tol_hz;
int time_correct_period;
bool sfo_correct_disable;
std::string sss_algorithm;
float estimator_fil_w;
bool rssi_sensor_enabled;
} phy_args_t;
/* Interface MAC -> PHY */
class phy_interface_mac
{
public:
/* Configure PRACH using parameters written by RRC */
virtual void configure_prach_params() = 0;
/* Start synchronization with strongest cell in the current carrier frequency */
virtual void sync_start() = 0;
virtual void sync_stop() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
virtual int prach_tx_tti() = 0;
/* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Time advance commands */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
virtual void set_timeadv(uint32_t ta_cmd) = 0;
/* Sets RAR grant payload */
virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0;
/* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
virtual void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_ul_search_reset() = 0;
virtual void pdcch_dl_search_reset() = 0;
virtual uint32_t get_current_tti() = 0;
virtual float get_phr() = 0;
virtual float get_pathloss_db() = 0;
};
class phy_interface_rrc
{
public:
typedef struct {
LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT prach_cnfg;
LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT pdsch_cnfg;
LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT pusch_cnfg;
LIBLTE_RRC_PHICH_CONFIG_STRUCT phich_cnfg;
LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT pucch_cnfg;
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg;
LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT ul_pwr_ctrl;
LIBLTE_RRC_TDD_CONFIG_STRUCT tdd_cnfg;
LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM ant_info;
} phy_cfg_common_t;
typedef struct {
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated;
phy_cfg_common_t common;
bool enable_64qam;
} phy_cfg_t;
virtual void get_current_cell(srslte_cell_t *cell) = 0;
virtual void get_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated) = 0;
virtual void set_config_common(phy_cfg_common_t *common) = 0;
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0;
/* Is the PHY downlink synchronized? */
virtual bool status_is_sync() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;
virtual void reset() = 0;
virtual void resync_sfn() = 0;
};
}
#endif

View File

@ -0,0 +1,151 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SECURITY_H
#define SECURITY_H
/******************************************************************************
* Common security header - wraps ciphering/integrity check algorithms.
*****************************************************************************/
#include "common/common.h"
#define SECURITY_DIRECTION_UPLINK 0
#define SECURITY_DIRECTION_DOWNLINK 1
namespace srsue{
typedef enum{
CIPHERING_ALGORITHM_ID_EEA0 = 0,
CIPHERING_ALGORITHM_ID_128_EEA1,
CIPHERING_ALGORITHM_ID_128_EEA2,
CIPHERING_ALGORITHM_ID_N_ITEMS,
}CIPHERING_ALGORITHM_ID_ENUM;
static const char ciphering_algorithm_id_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = {"EEA0",
"128-EEA1",
"128-EEA2"};
typedef enum{
INTEGRITY_ALGORITHM_ID_EIA0 = 0,
INTEGRITY_ALGORITHM_ID_128_EIA1,
INTEGRITY_ALGORITHM_ID_128_EIA2,
INTEGRITY_ALGORITHM_ID_N_ITEMS,
}INTEGRITY_ALGORITHM_ID_ENUM;
static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"EIA0",
"128-EIA1",
"128-EIA2"};
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme( uint8_t *ck,
uint8_t *ik,
uint8_t *ak,
uint8_t *sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t *k_asme);
uint8_t security_generate_k_enb( uint8_t *k_asme,
uint32_t nas_count,
uint8_t *k_enb);
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_nas_enc,
uint8_t *k_nas_int);
uint8_t security_generate_k_rrc( uint8_t *k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int);
uint8_t security_generate_k_up( uint8_t *k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_up_enc,
uint8_t *k_up_int);
/******************************************************************************
* Integrity Protection
*****************************************************************************/
uint8_t security_128_eia1( uint8_t *key,
uint32_t count,
uint8_t bearer,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac);
uint8_t security_128_eia2( uint8_t *key,
uint32_t count,
uint8_t bearer,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac);
/******************************************************************************
* Authentication
*****************************************************************************/
uint8_t security_milenage_f1( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *sqn,
uint8_t *amf,
uint8_t *mac_a);
uint8_t security_milenage_f1_star( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *sqn,
uint8_t *amf,
uint8_t *mac_s);
uint8_t security_milenage_f2345( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *res,
uint8_t *ck,
uint8_t *ik,
uint8_t *ak);
uint8_t security_milenage_f5_star( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *ak);
} // namespace srsue
#endif // SECURITY_H

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------
* snow_3g.h
*
* Adapted from ETSI/SAGE specifications:
* "Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2.
* Document 1: UEA2 and UIA2 Specification"
* "Specification of the 3GPP Confidentiality
* and Integrity Algorithms UEA2 & UIA2.
* Document 2: SNOW 3G Specification"
*---------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
* See Section 4.1.
*/
void snow3g_initialize(u32 k[4], u32 IV[4]);
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
* See section 4.2.
*/
void snow3g_generate_keystream(u32 n, u32 *z);
/* f8.
* Input key: 128 bit Confidentiality Key.
* Input count:32-bit Count, Frame dependent input.
* Input bearer: 5-bit Bearer identity (in the LSB side).
* Input dir:1 bit, direction of transmission.
* Input data: length number of bits, input bit stream.
* Input length: 32 bit Length, i.e., the number of bits to be encrypted or
* decrypted.
* Output data: Output bit stream. Assumes data is suitably memory
* allocated.
* Encrypts/decrypts blocks of data between 1 and 2^32 bits in length as
* defined in Section 3.
*/
void snow3g_f8( u8 *key, u32 count, u32 bearer, u32 dir, \
u8 *data, u32 length );
/* f9.
* Input key: 128 bit Integrity Key.
* Input count:32-bit Count, Frame dependent input.
* Input fresh: 32-bit Random number.
* Input dir:1 bit, direction of transmission (in the LSB).
* Input data: length number of bits, input bit stream.
* Input length: 64 bit Length, i.e., the number of bits to be MAC'd.
* Output : 32 bit block used as MAC
* Generates 32-bit MAC using UIA2 algorithm as defined in Section 4.
*/
u8* snow3g_f9( u8* key, u32 count, u32 fresh, u32 dir, \
u8 *data, u64 length);

View File

@ -0,0 +1,61 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: task_dispatcher.h
* Description:
* Reference:
*****************************************************************************/
#ifndef TASK_DISPATCHER_H
#define TASK_DISPATCHER_H
#include <pthread.h>
#include <stdint.h>
#include <string>
#include <queue>
#include "common/threads.h"
namespace srslte {
class task_dispatcher : public thread
{
public:
task_dispatcher(uint32_t max_pending_tasks);
~task_dispatcher();
void push_task(uint32_t task_code);
virtual void run_task(uint32_t task_code) = 0;
private:
std::queue<uint32_t> pending_tasks;
void run_thread();
pthread_mutex_t mutex;
pthread_cond_t cvar;
bool running;
};
} // namespace srsue
#endif // TASK_DISPATCHER_H

View File

@ -0,0 +1,105 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: thread_pool.h
* Description: Implements a pool of threads. Pending tasks to execute are
* identified by a pointer.
* Reference:
*****************************************************************************/
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <stdint.h>
#include <string>
#include <vector>
#include <stack>
#include "common/threads.h"
namespace srslte {
class thread_pool
{
public:
class worker : public thread
{
public:
void setup(uint32_t id, thread_pool *parent, uint32_t prio=0, uint32_t mask = 255);
void stop();
uint32_t get_id();
void release();
protected:
virtual void work_imp() = 0;
private:
uint32_t my_id;
thread_pool *my_parent;
bool running;
void run_thread();
void wait_to_start();
void finished();
};
thread_pool(uint32_t nof_workers);
void init_worker(uint32_t id, worker*, uint32_t prio = 0, uint32_t mask = 255);
void stop();
worker* wait_worker();
worker* wait_worker(uint32_t tti);
worker* wait_worker_nb(uint32_t tti);
void start_worker(worker*);
void start_worker(uint32_t id);
worker* get_worker(uint32_t id);
uint32_t get_nof_workers();
private:
bool find_finished_worker(uint32_t tti, uint32_t *id);
typedef enum {
IDLE,
START_WORK,
WORKER_READY,
WORKING
}worker_status;
std::vector<worker*> workers;
uint32_t nof_workers;
uint32_t max_workers;
bool running;
pthread_cond_t cvar_queue;
pthread_mutex_t mutex_queue;
std::vector<worker_status> status;
std::vector<pthread_cond_t> cvar;
std::vector<pthread_mutex_t> mutex;
std::stack<worker*> available_workers;
};
}
#endif

View File

@ -0,0 +1,151 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include <stdint.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg);
bool threads_new_rt_prio(pthread_t *thread, void *(*start_routine) (void*), void *arg, int prio_offset);
bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu, int prio_offset);
bool threads_new_rt_mask(pthread_t *thread, void *(*start_routine) (void*), void *arg, int mask, int prio_offset);
void threads_print_self();
#ifdef __cplusplus
}
#ifndef THREADS_
#define THREADS_
class thread
{
public:
bool start(int prio = -1) {
return threads_new_rt_prio(&_thread, thread_function_entry, this, prio);
}
bool start_cpu(int prio, int cpu) {
return threads_new_rt_cpu(&_thread, thread_function_entry, this, cpu, prio);
}
bool start_cpu_mask(int prio, int mask){
return threads_new_rt_mask(&_thread, thread_function_entry, this, mask, prio);
}
void print_priority() {
threads_print_self();
}
void wait_thread_finish() {
pthread_join(_thread, NULL);
}
void thread_cancel() {
pthread_cancel(_thread);
}
protected:
virtual void run_thread() = 0;
private:
static void *thread_function_entry(void *_this) { ((thread*) _this)->run_thread(); return NULL; }
pthread_t _thread;
};
class periodic_thread : public thread
{
public:
void start_periodic(int period_us_, int priority = -1) {
period_us = period_us_;
start(priority);
}
protected:
virtual void run_period() = 0;
private:
int wakeups_missed;
int timer_fd;
int period_us;
void run_thread() {
if (make_periodic()) {
return;
}
while(1) {
run_period();
wait_period();
}
}
int make_periodic() {
int ret = -1;
unsigned int ns;
unsigned int sec;
struct itimerspec itval;
/* Create the timer */
ret = timerfd_create (CLOCK_MONOTONIC, 0);
wakeups_missed = 0;
timer_fd = ret;
if (ret > 0) {
/* Make the timer periodic */
sec = period_us/1e6;
ns = (period_us - (sec * 1000000)) * 1000;
itval.it_interval.tv_sec = sec;
itval.it_interval.tv_nsec = ns;
itval.it_value.tv_sec = sec;
itval.it_value.tv_nsec = ns;
ret = timerfd_settime (timer_fd, 0, &itval, NULL);
if (ret < 0) {
perror("timerfd_settime");
}
} else {
perror("timerfd_create");
}
return ret;
}
void wait_period() {
unsigned long long missed;
int ret;
/* Wait for the next timer event. If we have missed any the
number is written to "missed" */
ret = read (timer_fd, &missed, sizeof (missed));
if (ret == -1)
{
perror ("read timer");
return;
}
/* "missed" should always be >= 1, but just to be sure, check it is not 0 anyway */
if (missed > 0) {
wakeups_missed += (missed - 1);
}
}
};
#endif // THREADS_
#endif // __cplusplus

View File

@ -0,0 +1,124 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: timeout.h
* Description: Millisecond resolution timeouts. Uses a dedicated thread to
* call an optional callback function upon timeout expiry.
* Reference:
*****************************************************************************/
#ifndef TIMEOUT_H
#define TIMEOUT_H
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
#include "srslte/srslte.h"
namespace srslte {
class timeout_callback
{
public:
virtual void timeout_expired(uint32_t timeout_id) = 0;
};
class timeout
{
public:
timeout():running(false),callback(NULL), thread(0), timeout_id(0) {}
~timeout()
{
if(running && callback)
pthread_join(thread, NULL);
}
void start(int duration_msec_, uint32_t timeout_id_=0,timeout_callback *callback_=NULL)
{
if(duration_msec_ < 0)
return;
reset();
gettimeofday(&start_time[1], NULL);
duration_msec = duration_msec_;
running = true;
timeout_id = timeout_id_;
callback = callback_;
if(callback)
pthread_create(&thread, NULL, &thread_start, this);
}
void reset()
{
if(callback)
pthread_cancel(thread);
running = false;
}
static void* thread_start(void *t_)
{
timeout *t = (timeout*)t_;
t->thread_func();
return NULL;
}
void thread_func()
{
// substract time elapsed until now from timer duration
gettimeofday(&start_time[2], NULL);
get_time_interval(start_time);
int32_t usec = duration_msec*1000-start_time[0].tv_usec;
if(usec > 0)
usleep(usec);
if(callback && running)
callback->timeout_expired(timeout_id);
}
bool expired()
{
if(running) {
gettimeofday(&start_time[2], NULL);
get_time_interval(start_time);
return start_time[0].tv_usec > duration_msec*1000;
} else {
return false;
}
}
bool is_running()
{
return running;
}
private:
struct timeval start_time[3];
pthread_t thread;
uint32_t timeout_id;
timeout_callback *callback;
bool running;
int duration_msec;
};
} // namespace srsue
#endif // TIMEOUT_H

View File

@ -0,0 +1,151 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: timers.h
* Description: Manually incremented timers. Call a callback function upon
* expiry.
* Reference:
*****************************************************************************/
#ifndef TIMERS_H
#define TIMERS_H
#include <stdio.h>
#include <stdint.h>
#include <vector>
#include <time.h>
namespace srslte {
class timer_callback
{
public:
virtual void timer_expired(uint32_t timer_id) = 0;
};
class timers
{
public:
class timer
{
public:
timer(uint32_t id_=0) {id = id_; counter = 0; timeout = 0; running = false; callback = NULL; }
void set(timer_callback *callback_, uint32_t timeout_) {
callback = callback_;
timeout = timeout_;
reset();
}
bool is_running() {
return (counter < timeout) && running;
}
bool is_expired() {
return callback && (counter >= timeout || !running);
}
uint32_t get_timeout() {
return timeout;
}
void reset() {
counter = 0;
}
void step() {
if (running) {
counter++;
if (is_expired()) {
running = false;
if (callback) {
callback->timer_expired(id);
}
}
}
}
void stop() {
running = false;
}
void run() {
running = true;
}
uint32_t id;
private:
timer_callback *callback;
uint32_t timeout;
uint32_t counter;
bool running;
};
timers(uint32_t nof_timers_) : timer_list(nof_timers_) {
nof_timers = nof_timers_;
next_timer = 0;
for (uint32_t i=0;i<nof_timers;i++) {
timer_list[i].id = i;
}
}
void step_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->step();
}
}
void stop_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->stop();
}
}
void run_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->run();
}
}
void reset_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->reset();
}
}
timer *get(uint32_t i) {
if (i < nof_timers) {
return &timer_list[i];
} else {
printf("Error accessing invalid timer %d (Only %d timers available)\n", i, nof_timers);
return NULL;
}
}
uint32_t get_unique_id() {
if (next_timer == nof_timers){
printf("No more unique timer ids (Only %d timers available)\n", nof_timers);
next_timer = 0;
}
return next_timer++;
}
private:
uint32_t nof_timers;
uint32_t next_timer;
std::vector<timer> timer_list;
};
} // namespace srslte
#endif // TIMERS_H

View File

@ -0,0 +1,101 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: trace.h
* Description:
* Reference:
*****************************************************************************/
#ifndef TRACE_H
#define TRACE_H
#include <stdio.h>
#include <string>
#include <vector>
namespace srslte {
template<class elemType>
class trace
{
public:
trace(uint32_t nof_elems_) : tti(nof_elems_), data(nof_elems_) {
rpm=0;
nof_elems=nof_elems_;
wrapped = false;
};
void push_cur_time_us(uint32_t cur_tti) {
struct timeval t;
gettimeofday(&t, NULL);
elemType us = t.tv_sec*1e6+t.tv_usec;
push(cur_tti, us);
}
void push(uint32_t value_tti, elemType value) {
tti[rpm] = value_tti;
data[rpm] = value;
rpm++;
if (rpm >= nof_elems) {
rpm = 0;
wrapped = true;
}
}
bool writeToBinary(std::string filename) {
FILE *f = fopen(filename.c_str(), "w");
if (f != NULL) {
uint32_t st=wrapped?(rpm+1):0;
do {
writeToBinaryValue(f, st++);
if (st >= nof_elems) {
st=0;
}
} while(st!=rpm);
fclose(f);
return true;
} else {
perror("fopen");
return false;
}
}
private:
std::vector<uint32_t> tti;
std::vector<elemType> data;
uint32_t rpm;
uint32_t nof_elems;
bool wrapped;
void writeToBinaryValue(FILE *f, uint32_t idx) {
fwrite(&tti[idx], 1, sizeof(uint32_t), f);
fwrite(&data[idx], 1, sizeof(elemType), f);
}
};
} // namespace srslte
#endif // TRACE_H

View File

@ -0,0 +1,78 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: tti_synch.h
* Description: Interface used for PHY-MAC synchronization
* (producer-consumer model). The consumer waits while its
* counter is lower than the producer counter.
* The PHY is the consumer. The MAC is the producer.
* Reference:
*****************************************************************************/
#ifndef TTISYNC_H
#define TTISYNC_H
#include <stdint.h>
namespace srslte {
class tti_sync
{
public:
tti_sync(uint32_t modulus_)
{
modulus = modulus_;
increment = 1;
init_counters(0);
}
virtual void increase() = 0;
virtual void resync() = 0;
virtual uint32_t wait() = 0;
virtual void set_producer_cntr(uint32_t) = 0;
uint32_t get_producer_cntr() { return producer_cntr; }
uint32_t get_consumer_cntr() { return consumer_cntr; }
void set_increment(uint32_t increment_) {
increment = increment_;
}
protected:
void increase_producer() { producer_cntr = (producer_cntr + increment)%modulus; }
void increase_consumer() { consumer_cntr = (consumer_cntr + increment)%modulus; }
bool wait_condition() { return producer_cntr == consumer_cntr; }
void init_counters(uint32_t val)
{
consumer_cntr = val;
producer_cntr = val;
}
uint32_t increment;
uint32_t modulus;
uint32_t producer_cntr;
uint32_t consumer_cntr;
};
} // namespace srsue
#endif // TTISYNC_H

View File

@ -0,0 +1,58 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: tti_synch_cv.h
* Description: Implements tti_sync interface with condition variables.
* Reference:
*****************************************************************************/
#ifndef TTISYNC_CV_H
#define TTISYNC_CV_H
#include <pthread.h>
#include "common/tti_sync.h"
namespace srslte {
class tti_sync_cv : public tti_sync
{
public:
tti_sync_cv(uint32_t modulus = 10240);
~tti_sync_cv();
void increase();
uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr);
private:
pthread_cond_t cond;
pthread_mutex_t mutex;
};
} // namespace srsue
#endif // TTISYNC_CV_H

View File

@ -0,0 +1,25 @@
#
# Copyright 2013-2015 Software Radio Systems Limited
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
file(GLOB CXX_SOURCES "*.cc")
file(GLOB C_SOURCES "*.c")
add_library(srslte_common SHARED ${C_SOURCES} ${CXX_SOURCES})
INSTALL(TARGETS srslte_common DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srslte_common)

View File

@ -0,0 +1,65 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include "common/buffer_pool.h"
#include <stdio.h>
#include <string>
namespace srslte{
byte_buffer_pool *byte_buffer_pool::instance = NULL;
pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
byte_buffer_pool* byte_buffer_pool::get_instance(void)
{
pthread_mutex_lock(&instance_mutex);
if(NULL == instance)
instance = new byte_buffer_pool();
pthread_mutex_unlock(&instance_mutex);
return instance;
}
void byte_buffer_pool::cleanup(void)
{
pthread_mutex_lock(&instance_mutex);
if(NULL != instance)
{
delete instance;
instance = NULL;
}
pthread_mutex_unlock(&instance_mutex);
}
} // namespace srsue

View File

@ -0,0 +1,316 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <sys/time.h>
#include "common/log_filter.h"
namespace srslte{
log_filter::log_filter()
{
do_tti = false;
}
log_filter::log_filter(std::string layer, logger *logger_, bool tti)
{
init(layer, logger_, tti);
}
void log_filter::init(std::string layer, logger *logger_, bool tti)
{
service_name = layer;
logger_h = logger_;
do_tti = tti;
}
void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg)
{
if(logger_h) {
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
if(do_tti)
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
str_ptr s_ptr(new std::string(ss.str()));
logger_h->log(s_ptr);
}
}
void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg,
uint8_t *hex,
int size)
{
if(logger_h) {
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
if(do_tti)
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
if (msg[strlen(msg)-1] != '\n') {
ss << std::endl;
}
if (hex_limit > 0) {
ss << hex_string(hex, size);
}
str_ptr s_ptr(new std::string(ss.str()));
logger_h->log(s_ptr);
}
}
void log_filter::all_log_line(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
std::string file,
int line,
char *msg)
{
if(logger_h) {
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
if(do_tti)
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
str_ptr s_ptr(new std::string(ss.str()));
logger_h->log(s_ptr);
}
}
void log_filter::console(std::string message, ...) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
printf("%s",args_msg); // Print directly to stdout
va_end(args);
free(args_msg);
}
void log_filter::error(std::string message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_ERROR, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::warning(std::string message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_WARNING, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::info(std::string message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_INFO, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::debug(std::string message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_DEBUG, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::error_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_ERROR, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_filter::warning_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_WARNING, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_filter::info_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_INFO, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_filter::debug_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log(LOG_LEVEL_DEBUG, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_filter::error_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log_line(LOG_LEVEL_ERROR, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::warning_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log_line(LOG_LEVEL_WARNING, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::info_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log_line(LOG_LEVEL_INFO, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_filter::debug_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
all_log_line(LOG_LEVEL_DEBUG, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
std::string log_filter::now_time()
{
struct timeval rawtime;
struct tm * timeinfo;
char buffer[64];
char us[16];
gettimeofday(&rawtime, NULL);
timeinfo = localtime(&rawtime.tv_sec);
strftime(buffer,64,"%H:%M:%S",timeinfo);
strcat(buffer,".");
snprintf(us,16,"%06ld",rawtime.tv_usec);
strcat(buffer,us);
return std::string(buffer);
}
std::string log_filter::hex_string(uint8_t *hex, int size)
{
std::stringstream ss;
int c = 0;
ss << std::hex << std::setfill('0');
if(hex_limit >= 0) {
size = (size > hex_limit) ? hex_limit : size;
}
while(c < size) {
ss << " " << std::setw(4) << static_cast<unsigned>(c) << ": ";
int tmp = (size-c < 16) ? size-c : 16;
for(int i=0;i<tmp;i++) {
ss << std::setw(2) << static_cast<unsigned>(hex[c++]) << " ";
}
ss << "\n";
}
return ss.str();
}
} // namespace srsue

View File

@ -0,0 +1,290 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <stdarg.h>
#include <string>
#include "common/log_stdout.h"
using namespace std;
namespace srslte {
void log_stdout::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
cout << ss.str();
}
void log_stdout::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg,
uint8_t *hex,
int size)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg << std::endl;
ss << hex_string(hex, size);
cout << ss.str();
}
void log_stdout::all_log_line(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
std::string file,
int line,
char *msg)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
cout << ss.str();
}
void log_stdout::console(std::string message, ...) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
printf("%s",args_msg); // Print directly to stdout
va_end(args);
free(args_msg);
}
void log_stdout::error(std::string message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_ERROR, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::warning(std::string message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_WARNING, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::info(std::string message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_INFO, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::debug(std::string message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_DEBUG, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::error_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_ERROR, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::warning_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_WARNING, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::info_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_INFO, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::debug_hex(uint8_t *hex, int size, std::string message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log(LOG_LEVEL_DEBUG, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::error_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log_line(LOG_LEVEL_ERROR, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::warning_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log_line(LOG_LEVEL_WARNING, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::info_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log_line(LOG_LEVEL_INFO, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::debug_line(std::string file, int line, std::string message, ...)
{
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0);
all_log_line(LOG_LEVEL_DEBUG, tti, file, line, args_msg);
va_end(args);
free(args_msg);
}
}
std::string log_stdout::now_time()
{
struct timeval rawtime;
struct tm * timeinfo;
char buffer[64];
char us[16];
gettimeofday(&rawtime, NULL);
timeinfo = localtime(&rawtime.tv_sec);
strftime(buffer,64,"%H:%M:%S",timeinfo);
strcat(buffer,".");
snprintf(us,16,"%ld",rawtime.tv_usec);
strcat(buffer,us);
return std::string(buffer);
}
std::string log_stdout::hex_string(uint8_t *hex, int size)
{
std::stringstream ss;
int c = 0;
ss << std::hex << std::setfill('0');
if(hex_limit >= 0) {
size = (size > hex_limit) ? hex_limit : size;
}
while(c < size) {
ss << " " << std::setw(4) << static_cast<unsigned>(c) << ": ";
int tmp = (size-c < 16) ? size-c : 16;
for(int i=0;i<tmp;i++) {
ss << std::setw(2) << static_cast<unsigned>(hex[c++]) << " ";
}
ss << "\n";
}
return ss.str();
}
}

103
srslte/lib/common/logger.cc Normal file
View File

@ -0,0 +1,103 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define LOG_BUFFER_SIZE 1024*32
#include "common/logger.h"
using namespace std;
namespace srslte{
logger::logger()
:inited(false)
,not_done(true)
{}
logger::~logger() {
not_done = false;
log("Closing log");
if(inited) {
wait_thread_finish();
flush();
fclose(logfile);
}
}
void logger::init(std::string file) {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&not_empty, NULL);
pthread_cond_init(&not_full, NULL);
filename = file;
logfile = fopen(filename.c_str(), "w");
if(logfile==NULL) {
printf("Error: could not create log file, no messages will be logged");
}
start();
inited = true;
}
void logger::log(const char *msg) {
str_ptr s_ptr(new std::string(msg));
log(s_ptr);
}
void logger::log(str_ptr msg) {
pthread_mutex_lock(&mutex);
buffer.push_back(msg);
pthread_cond_signal(&not_empty);
pthread_mutex_unlock(&mutex);
}
void logger::run_thread() {
while(not_done) {
pthread_mutex_lock(&mutex);
while(buffer.empty()) {
pthread_cond_wait(&not_empty, &mutex);
}
str_ptr s = buffer.front();
pthread_cond_signal(&not_full);
if(logfile)
fprintf(logfile, "%s", s->c_str());
delete s;
buffer.pop_front();
pthread_mutex_unlock(&mutex);
}
}
void logger::flush() {
std::deque<str_ptr>::iterator it;
for(it=buffer.begin();it!=buffer.end();it++)
{
str_ptr s = *it;
if(logfile)
fprintf(logfile, "%s", s->c_str());
delete s;
}
}
} // namespace srsue

View File

@ -0,0 +1,99 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srslte/srslte.h"
#include "common/pcap.h"
#include "common/mac_pcap.h"
namespace srslte {
void mac_pcap::enable(bool en)
{
enable_write = true;
}
void mac_pcap::open(const char* filename, uint32_t ue_id)
{
pcap_file = MAC_LTE_PCAP_Open(filename);
ue_id = ue_id;
enable_write = true;
}
void mac_pcap::close()
{
fprintf(stdout, "Saving PCAP file\n");
MAC_LTE_PCAP_Close(pcap_file);
}
void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
uint16_t crnti, uint8_t direction, uint8_t rnti_type)
{
if (enable_write) {
MAC_Context_Info_t context =
{
FDD_RADIO, direction, rnti_type,
crnti, /* RNTI */
ue_id, /* UEId */
reTX, /* Retx */
crc_ok, /* CRC Stsatus (i.e. OK) */
tti/10, /* Sysframe number */
tti%10 /* Subframe number */
};
if (pdu) {
MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
}
}
}
void mac_pcap::write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, bool crc_ok, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
}
void mac_pcap::write_dl_ranti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, bool crc_ok, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, rnti, DIRECTION_DOWNLINK, RA_RNTI);
}
void mac_pcap::write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint32_t reTX, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, reTX, true, tti, rnti, DIRECTION_UPLINK, C_RNTI);
}
void mac_pcap::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, 0, DIRECTION_DOWNLINK, NO_RNTI);
}
void mac_pcap::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, SRSLTE_PRNTI, DIRECTION_DOWNLINK, P_RNTI);
}
void mac_pcap::write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti)
{
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI);
}
}

1000
srslte/lib/common/pdu.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#include "common/pdu_queue.h"
namespace srslte {
void pdu_queue::init(process_callback *callback_, log* log_h_)
{
callback = callback_;
log_h = log_h_;
}
uint8_t* pdu_queue::request(uint32_t len)
{
if (len > MAX_PDU_LEN) {
fprintf(stderr, "Error request buffer of invalid size %d. Max bytes %d\n", len, MAX_PDU_LEN);
return NULL;
}
pdu_t *pdu = pool.allocate();
if (!pdu) {
if (log_h) {
log_h->error("Not enough buffers for MAC PDU\n");
}
fprintf(stderr, "Not enough buffers for MAC PDU\n");
}
if ((void*) pdu->ptr != (void*) pdu) {
fprintf(stderr, "Fatal error in memory alignment in struct pdu_queue::pdu_t\n");
exit(-1);
}
return pdu->ptr;
}
void pdu_queue::deallocate(uint8_t* pdu)
{
if (!pool.deallocate((pdu_t*) pdu)) {
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
}
}
/* Demultiplexing of logical channels and dissassemble of MAC CE
* This function enqueues the packet and returns quicly because ACK
* deadline is important here.
*/
void pdu_queue::push(uint8_t *ptr, uint32_t len)
{
pdu_t *pdu = (pdu_t*) ptr;
pdu->len = len;
pdu_q.push(pdu);
}
bool pdu_queue::process_pdus()
{
bool have_data = false;
uint32_t cnt = 0;
pdu_t *pdu;
while(pdu_q.try_pop(&pdu)) {
if (callback) {
callback->process_pdu(pdu->ptr, pdu->len);
}
if (!pool.deallocate(pdu)) {
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
}
cnt++;
have_data = true;
}
if (cnt > 20) {
if (log_h) {
log_h->warning("PDU queue dispatched %d packets\n", cnt);
}
printf("Warning PDU queue dispatched %d packets\n", cnt);
}
return have_data;
}
}

View File

@ -0,0 +1,214 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "common/security.h"
#include "liblte_security.h"
#include "common/snow_3g.h"
using namespace srslte;
namespace srsue{
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme( uint8_t *ck,
uint8_t *ik,
uint8_t *ak,
uint8_t *sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t *k_asme)
{
return liblte_security_generate_k_asme(ck,
ik,
ak,
sqn,
mcc,
mnc,
k_asme);
}
uint8_t security_generate_k_enb( uint8_t *k_asme,
uint32_t nas_count,
uint8_t *k_enb)
{
return liblte_security_generate_k_enb(k_asme,
nas_count,
k_enb);
}
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_nas_enc,
uint8_t *k_nas_int)
{
return liblte_security_generate_k_nas( k_asme,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_nas_enc,
k_nas_int);
}
uint8_t security_generate_k_rrc( uint8_t *k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int)
{
return liblte_security_generate_k_rrc(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_rrc_enc,
k_rrc_int);
}
uint8_t security_generate_k_up( uint8_t *k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t *k_up_enc,
uint8_t *k_up_int)
{
return liblte_security_generate_k_up(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_up_enc,
k_up_int);
}
/******************************************************************************
* Integrity Protection
*****************************************************************************/
uint8_t security_128_eia1( uint8_t *key,
uint32_t count,
uint8_t bearer,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac)
{
uint32_t msg_len_bits;
uint32_t i;
uint8_t *m_ptr;
msg_len_bits = msg_len*8;
m_ptr = snow3g_f9(key,
count,
bearer,
direction,
msg,
msg_len_bits);
for(i=0; i<4; i++) {
mac[i] = m_ptr[i];
}
return ERROR_NONE;
}
uint8_t security_128_eia2( uint8_t *key,
uint32_t count,
uint8_t bearer,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac)
{
return liblte_security_128_eia2(key,
count,
bearer,
direction,
msg,
msg_len,
mac);
}
/******************************************************************************
* Authentication
*****************************************************************************/
uint8_t security_milenage_f1( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *sqn,
uint8_t *amf,
uint8_t *mac_a)
{
return liblte_security_milenage_f1(k,
op,
rand,
sqn,
amf,
mac_a);
}
uint8_t security_milenage_f1_star( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *sqn,
uint8_t *amf,
uint8_t *mac_s)
{
return liblte_security_milenage_f1_star(k,
op,
rand,
sqn,
amf,
mac_s);
}
uint8_t security_milenage_f2345( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *res,
uint8_t *ck,
uint8_t *ik,
uint8_t *ak)
{
return liblte_security_milenage_f2345(k,
op,
rand,
res,
ck,
ik,
ak);
}
uint8_t security_milenage_f5_star( uint8_t *k,
uint8_t *op,
uint8_t *rand,
uint8_t *ak)
{
return liblte_security_milenage_f5_star(k,
op,
rand,
ak);
}
} // namespace srsue

View File

@ -0,0 +1,577 @@
/*------------------------------------------------------------------------
* snow_3g.c
*
* Adapted from ETSI/SAGE specifications:
* "Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2.
* Document 1: UEA2 and UIA2 Specification"
* "Specification of the 3GPP Confidentiality
* and Integrity Algorithms UEA2 & UIA2.
* Document 2: SNOW 3G Specification"
*------------------------------------------------------------------------*/
#include "common/snow_3g.h"
/* LFSR */
u32 LFSR_S0 = 0x00;
u32 LFSR_S1 = 0x00;
u32 LFSR_S2 = 0x00;
u32 LFSR_S3 = 0x00;
u32 LFSR_S4 = 0x00;
u32 LFSR_S5 = 0x00;
u32 LFSR_S6 = 0x00;
u32 LFSR_S7 = 0x00;
u32 LFSR_S8 = 0x00;
u32 LFSR_S9 = 0x00;
u32 LFSR_S10 = 0x00;
u32 LFSR_S11 = 0x00;
u32 LFSR_S12 = 0x00;
u32 LFSR_S13 = 0x00;
u32 LFSR_S14 = 0x00;
u32 LFSR_S15 = 0x00;
/* FSM */
u32 FSM_R1 = 0x00;
u32 FSM_R2 = 0x00;
u32 FSM_R3 = 0x00;
/* Rijndael S-box SR */
u8 SR[256] = {
0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16
};
/* S-box SQ */
u8 SQ[256] = {
0x25,0x24,0x73,0x67,0xD7,0xAE,0x5C,0x30,0xA4,0xEE,0x6E,0xCB,0x7D,0xB5,0x82,0xDB,
0xE4,0x8E,0x48,0x49,0x4F,0x5D,0x6A,0x78,0x70,0x88,0xE8,0x5F,0x5E,0x84,0x65,0xE2,
0xD8,0xE9,0xCC,0xED,0x40,0x2F,0x11,0x28,0x57,0xD2,0xAC,0xE3,0x4A,0x15,0x1B,0xB9,
0xB2,0x80,0x85,0xA6,0x2E,0x02,0x47,0x29,0x07,0x4B,0x0E,0xC1,0x51,0xAA,0x89,0xD4,
0xCA,0x01,0x46,0xB3,0xEF,0xDD,0x44,0x7B,0xC2,0x7F,0xBE,0xC3,0x9F,0x20,0x4C,0x64,
0x83,0xA2,0x68,0x42,0x13,0xB4,0x41,0xCD,0xBA,0xC6,0xBB,0x6D,0x4D,0x71,0x21,0xF4,
0x8D,0xB0,0xE5,0x93,0xFE,0x8F,0xE6,0xCF,0x43,0x45,0x31,0x22,0x37,0x36,0x96,0xFA,
0xBC,0x0F,0x08,0x52,0x1D,0x55,0x1A,0xC5,0x4E,0x23,0x69,0x7A,0x92,0xFF,0x5B,0x5A,
0xEB,0x9A,0x1C,0xA9,0xD1,0x7E,0x0D,0xFC,0x50,0x8A,0xB6,0x62,0xF5,0x0A,0xF8,0xDC,
0x03,0x3C,0x0C,0x39,0xF1,0xB8,0xF3,0x3D,0xF2,0xD5,0x97,0x66,0x81,0x32,0xA0,0x00,
0x06,0xCE,0xF6,0xEA,0xB7,0x17,0xF7,0x8C,0x79,0xD6,0xA7,0xBF,0x8B,0x3F,0x1F,0x53,
0x63,0x75,0x35,0x2C,0x60,0xFD,0x27,0xD3,0x94,0xA5,0x7C,0xA1,0x05,0x58,0x2D,0xBD,
0xD9,0xC7,0xAF,0x6B,0x54,0x0B,0xE0,0x38,0x04,0xC8,0x9D,0xE7,0x14,0xB1,0x87,0x9C,
0xDF,0x6F,0xF9,0xDA,0x2A,0xC4,0x59,0x16,0x74,0x91,0xAB,0x26,0x61,0x76,0x34,0x2B,
0xAD,0x99,0xFB,0x72,0xEC,0x33,0x12,0xDE,0x98,0x3B,0xC0,0x9B,0x3E,0x18,0x10,0x3A,
0x56,0xE1,0x77,0xC9,0x1E,0x9E,0x95,0xA3,0x90,0x19,0xA8,0x6C,0x09,0xD0,0xF0,0x86
};
/* MULx.
* Input V: an 8-bit input.
* Input c: an 8-bit input.
* Output : an 8-bit output.
* See section 3.1.1 for details.
*/
u8 MULx(u8 V, u8 c)
{
if ( V & 0x80 )
return ( (V << 1) ^ c);
else
return ( V << 1);
}
/* MULxPOW.
* Input V: an 8-bit input.
* Input i: a positive integer.
* Input c: an 8-bit input.
* Output : an 8-bit output.
* See section 3.1.2 for details.
*/
u8 MULxPOW(u8 V, u8 i, u8 c)
{
if ( i == 0)
return V;
else
return MULx( MULxPOW( V, i-1, c ), c);
}
/* The function MUL alpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* See section 3.4.2 for details.
*/
u32 MULalpha(u8 c)
{
return ( ( ((u32)MULxPOW(c, 23, 0xa9)) << 24 ) |
( ((u32)MULxPOW(c, 245, 0xa9)) << 16 ) |
( ((u32)MULxPOW(c, 48, 0xa9)) << 8 ) |
( ((u32)MULxPOW(c, 239, 0xa9)) ) ) ;
}
/* The function DIV alpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* See section 3.4.3 for details.
*/
u32 DIValpha(u8 c)
{
return ( ( ((u32)MULxPOW(c, 16, 0xa9)) << 24 ) |
( ((u32)MULxPOW(c, 39, 0xa9)) << 16 ) |
( ((u32)MULxPOW(c, 6, 0xa9)) << 8 ) |
( ((u32)MULxPOW(c, 64, 0xa9)) ) ) ;
}
/* The 32x32-bit S-Box S1
* Input: a 32-bit input.
* Output: a 32-bit output of S1 box.
* See section 3.3.1.
*/
u32 S1(u32 w)
{
u8 r0=0, r1=0, r2=0, r3=0;
u8 srw0 = SR[ (u8)((w >> 24) & 0xff) ];
u8 srw1 = SR[ (u8)((w >> 16) & 0xff) ];
u8 srw2 = SR[ (u8)((w >> 8) & 0xff) ];
u8 srw3 = SR[ (u8)((w) & 0xff) ];
r0 = ( ( MULx( srw0 , 0x1b) ) ^
( srw1 ) ^
( srw2 ) ^
( (MULx( srw3, 0x1b)) ^ srw3 )
);
r1 = ( ( ( MULx( srw0 , 0x1b) ) ^ srw0 ) ^
( MULx(srw1, 0x1b) ) ^
( srw2 ) ^
( srw3 )
);
r2 = ( ( srw0 ) ^
( ( MULx( srw1 , 0x1b) ) ^ srw1 ) ^
( MULx(srw2, 0x1b) ) ^
( srw3 )
);
r3 = ( ( srw0 ) ^
( srw1 ) ^
( ( MULx( srw2 , 0x1b) ) ^ srw2 ) ^
( MULx( srw3, 0x1b) )
);
return ( ( ((u32)r0) << 24 ) | ( ((u32)r1) << 16 ) | ( ((u32)r2) << 8 ) |
( ((u32)r3) ) );
}
/* The 32x32-bit S-Box S2
* Input: a 32-bit input.
* Output: a 32-bit output of S2 box.
* See section 3.3.2.
*/
u32 S2(u32 w)
{
u8 r0=0, r1=0, r2=0, r3=0;
u8 sqw0 = SQ[ (u8)((w >> 24) & 0xff) ];
u8 sqw1 = SQ[ (u8)((w >> 16) & 0xff) ];
u8 sqw2 = SQ[ (u8)((w >> 8) & 0xff) ];
u8 sqw3 = SQ[ (u8)((w) & 0xff) ];
r0 = ( ( MULx( sqw0 , 0x69) ) ^
( sqw1 ) ^
( sqw2 ) ^
( (MULx( sqw3, 0x69)) ^ sqw3 )
);
r1 = ( ( ( MULx( sqw0 , 0x69) ) ^ sqw0 ) ^
( MULx(sqw1, 0x69) ) ^
( sqw2 ) ^
( sqw3 )
);
r2 = ( ( sqw0 ) ^
( ( MULx( sqw1 , 0x69) ) ^ sqw1 ) ^
( MULx(sqw2, 0x69) ) ^
( sqw3 )
);
r3 = ( ( sqw0 ) ^
( sqw1 ) ^
( ( MULx( sqw2 , 0x69) ) ^ sqw2 ) ^
( MULx( sqw3, 0x69) )
);
return ( ( ((u32)r0) << 24 ) | ( ((u32)r1) << 16 ) | ( ((u32)r2) << 8 ) |
( ((u32)r3) ) );
}
/* Clocking LFSR in initialization mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* Input F: a 32-bit word comes from output of FSM.
* See section 3.4.4.
*/
void ClockLFSRInitializationMode(u32 F)
{
u32 v = ( ( (LFSR_S0 << 8) & 0xffffff00 ) ^
( MULalpha( (u8)((LFSR_S0>>24) & 0xff) ) ) ^
( LFSR_S2 ) ^
( (LFSR_S11 >> 8) & 0x00ffffff ) ^
( DIValpha( (u8)( ( LFSR_S11) & 0xff ) ) ) ^
( F )
);
LFSR_S0 = LFSR_S1;
LFSR_S1 = LFSR_S2;
LFSR_S2 = LFSR_S3;
LFSR_S3 = LFSR_S4;
LFSR_S4 = LFSR_S5;
LFSR_S5 = LFSR_S6;
LFSR_S6 = LFSR_S7;
LFSR_S7 = LFSR_S8;
LFSR_S8 = LFSR_S9;
LFSR_S9 = LFSR_S10;
LFSR_S10 = LFSR_S11;
LFSR_S11 = LFSR_S12;
LFSR_S12 = LFSR_S13;
LFSR_S13 = LFSR_S14;
LFSR_S14 = LFSR_S15;
LFSR_S15 = v;
}
/* Clocking LFSR in keystream mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* See section 3.4.5.
*/
void ClockLFSRKeyStreamMode()
{
u32 v = ( ( (LFSR_S0 << 8) & 0xffffff00 ) ^
( MULalpha( (u8)((LFSR_S0>>24) & 0xff) ) ) ^
( LFSR_S2 ) ^
( (LFSR_S11 >> 8) & 0x00ffffff ) ^
( DIValpha( (u8)( ( LFSR_S11) & 0xff ) ) )
);
LFSR_S0 = LFSR_S1;
LFSR_S1 = LFSR_S2;
LFSR_S2 = LFSR_S3;
LFSR_S3 = LFSR_S4;
LFSR_S4 = LFSR_S5;
LFSR_S5 = LFSR_S6;
LFSR_S6 = LFSR_S7;
LFSR_S7 = LFSR_S8;
LFSR_S8 = LFSR_S9;
LFSR_S9 = LFSR_S10;
LFSR_S10 = LFSR_S11;
LFSR_S11 = LFSR_S12;
LFSR_S12 = LFSR_S13;
LFSR_S13 = LFSR_S14;
LFSR_S14 = LFSR_S15;
LFSR_S15 = v;
}
/* Clocking FSM.
* Produces a 32-bit word F.
* Updates FSM registers R1, R2, R3.
* See Section 3.4.6.
*/
u32 ClockFSM()
{
u32 F = ( ( LFSR_S15 + FSM_R1 ) & 0xffffffff ) ^ FSM_R2 ;
u32 r = ( FSM_R2 + ( FSM_R3 ^ LFSR_S5 ) ) & 0xffffffff ;
FSM_R3 = S2(FSM_R2);
FSM_R2 = S1(FSM_R1);
FSM_R1 = r;
return F;
}
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
* See Section 4.1.
*/
void snow3g_initialize(u32 k[4], u32 IV[4])
{
u8 i=0;
u32 F = 0x0;
LFSR_S15 = k[3] ^ IV[0];
LFSR_S14 = k[2];
LFSR_S13 = k[1];
LFSR_S12 = k[0] ^ IV[1];
LFSR_S11 = k[3] ^ 0xffffffff;
LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2];
LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3];
LFSR_S8 = k[0] ^ 0xffffffff;
LFSR_S7 = k[3];
LFSR_S6 = k[2];
LFSR_S5 = k[1];
LFSR_S4 = k[0];
LFSR_S3 = k[3] ^ 0xffffffff;
LFSR_S2 = k[2] ^ 0xffffffff;
LFSR_S1 = k[1] ^ 0xffffffff;
LFSR_S0 = k[0] ^ 0xffffffff;
FSM_R1 = 0x0;
FSM_R2 = 0x0;
FSM_R3 = 0x0;
for(i=0;i<32;i++)
{
F = ClockFSM();
ClockLFSRInitializationMode(F);
}
}
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
* See section 4.2.
*/
void snow3g_generate_keystream(u32 n, u32 *ks)
{
u32 t = 0;
u32 F = 0x0;
ClockFSM(); /* Clock FSM once. Discard the output. */
ClockLFSRKeyStreamMode(); /* Clock LFSR in keystream mode once. */
for ( t=0; t<n; t++)
{
F = ClockFSM(); /* STEP 1 */
ks[t] = F ^ LFSR_S0; /* STEP 2 */
/* Note that ks[t] corresponds to z_{t+1} in section 4.2
*/
ClockLFSRKeyStreamMode(); /* STEP 3 */
}
}
/* f8.
* Input key: 128 bit Confidentiality Key.
* Input count:32-bit Count, Frame dependent input.
* Input bearer: 5-bit Bearer identity (in the LSB side).
* Input dir:1 bit, direction of transmission.
* Input data: length number of bits, input bit stream.
* Input length: 32 bit Length, i.e., the number of bits to be encrypted or
* decrypted.
* Output data: Output bit stream. Assumes data is suitably memory
* allocated.
* Encrypts/decrypts blocks of data between 1 and 2^32 bits in length as
* defined in Section 3.
*/
void snow3g_f8(u8 *key, u32 count, u32 bearer, u32 dir, u8 *data, u32 length)
{
u32 K[4],IV[4];
int n = ( length + 31 ) / 32;
int i=0;
int lastbits = (8-(length%8)) % 8;
u32 *KS;
/*Initialisation*/
/* Load the confidentiality key for SNOW 3G initialization as in section
3.4. */
for (i=0; i<4; i++)
K[3-i] = (key[4*i] << 24) ^ (key[4*i+1] << 16)
^ (key[4*i+2] << 8) ^ (key[4*i+3]);
/* Prepare the initialization vector (IV) for SNOW 3G initialization as in
section 3.4. */
IV[3] = count;
IV[2] = (bearer << 27) | ((dir & 0x1) << 26);
IV[1] = IV[3];
IV[0] = IV[2];
/* Run SNOW 3G algorithm to generate sequence of key stream bits KS*/
snow3g_initialize(K,IV);
KS = (u32 *)malloc(4*n);
snow3g_generate_keystream(n,(u32*)KS);
/* Exclusive-OR the input data with keystream to generate the output bit
stream */
for (i=0; i<n; i++)
{
data[4*i+0] ^= (u8) (KS[i] >> 24) & 0xff;
data[4*i+1] ^= (u8) (KS[i] >> 16) & 0xff;
data[4*i+2] ^= (u8) (KS[i] >> 8) & 0xff;
data[4*i+3] ^= (u8) (KS[i] ) & 0xff;
}
free(KS);
/* zero last bits of data in case its length is not byte-aligned
this is an addition to the C reference code, which did not handle it */
if (lastbits)
data[length/8] &= 256 - (1<<lastbits);
}
/* MUL64x.
* Input V: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.2 for details.
*/
u64 MUL64x(u64 V, u64 c)
{
if ( V & 0x8000000000000000 )
return (V << 1) ^ c;
else
return V << 1;
}
/* MUL64xPOW.
* Input V: a 64-bit input.
* Input i: a positive integer.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling function.
* See section 4.3.3 for details.
*/
u64 MUL64xPOW(u64 V, u8 i, u64 c)
{
if ( i == 0)
return V;
else
return MUL64x( MUL64xPOW(V,i-1,c) , c);
}
/* MUL64.
* Input V: a 64-bit input.
* Input P: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.4 for details.
*/
u64 MUL64(u64 V, u64 P, u64 c)
{
u64 result = 0;
int i = 0;
for ( i=0; i<64; i++)
{
if( ( P>>i ) & 0x1 )
result ^= MUL64xPOW(V,i,c);
}
return result;
}
/* mask8bit.
* Input n: an integer in 1-7.
* Output : an 8 bit mask.
* Prepares an 8 bit mask with required number of 1 bits on the MSB side.
*/
u8 mask8bit(int n)
{
return 0xFF ^ ((1<<(8-n)) - 1);
}
/* f9.
* Input key: 128 bit Integrity Key.
* Input count:32-bit Count, Frame dependent input.
* Input fresh: 32-bit Random number.
* Input dir:1 bit, direction of transmission (in the LSB).
* Input data: length number of bits, input bit stream.
* Input length: 64 bit Length, i.e., the number of bits to be MAC'd.
* Output : 32 bit block used as MAC
* Generates 32-bit MAC using UIA2 algorithm as defined in Section 4.
*/
u8* snow3g_f9( u8* key, u32 count, u32 fresh, u32 dir, u8 *data, u64 length)
{
u32 K[4],IV[4], z[5];
u32 i=0, D;
static u8 MAC_I[4] = {0,0,0,0}; /* static memory for the result */
u64 EVAL;
u64 V;
u64 P;
u64 Q;
u64 c;
u64 M_D_2;
int rem_bits = 0;
/* Load the Integrity Key for SNOW3G initialization as in section 4.4. */
for (i=0; i<4; i++)
K[3-i] = (key[4*i] << 24) ^ (key[4*i+1] << 16) ^
(key[4*i+2] << 8) ^ (key[4*i+3]);
/* Prepare the Initialization Vector (IV) for SNOW3G initialization as
in section 4.4. */
IV[3] = count;
IV[2] = fresh;
IV[1] = count ^ ( dir << 31 ) ;
IV[0] = fresh ^ (dir << 15);
z[0] = z[1] = z[2] = z[3] = z[4] = 0;
/* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */
snow3g_initialize(K, IV);
snow3g_generate_keystream(5, z);
P = (u64)z[0] << 32 | (u64)z[1];
Q = (u64)z[2] << 32 | (u64)z[3];
/* Calculation */
if ((length % 64) == 0)
D = (length>>6) + 1;
else
D = (length>>6) + 2;
EVAL = 0;
c = 0x1b;
/* for 0 <= i <= D-3 */
for (i=0; i<D-2; i++)
{
V = EVAL ^ ( (u64)data[8*i ]<<56 | (u64)data[8*i+1]<<48 |
(u64)data[8*i+2]<<40 | (u64)data[8*i+3]<<32 |
(u64)data[8*i+4]<<24 | (u64)data[8*i+5]<<16 |
(u64)data[8*i+6]<< 8 | (u64)data[8*i+7] ) ;
EVAL = MUL64(V,P,c);
}
/* for D-2 */
rem_bits = length % 64;
if (rem_bits == 0)
rem_bits = 64;
M_D_2 = 0;
i = 0;
while (rem_bits > 7)
{
M_D_2 |= (u64)data[8*(D-2)+i] << (8*(7-i));
rem_bits -= 8;
i++;
}
if (rem_bits > 0)
M_D_2 |= (u64)(data[8*(D-2)+i] & mask8bit(rem_bits)) << (8*(7-i));
V = EVAL ^ M_D_2;
EVAL = MUL64(V,P,c);
/* for D-1 */
EVAL ^= length;
/* Multiply by Q */
EVAL = MUL64(EVAL,Q,c);
/* XOR with z_5: this is a modification to the reference C code,
which forgot to XOR z[5] */
for (i=0; i<4; i++)
/*
MAC_I[i] = (mac32 >> (8*(3-i))) & 0xff;
*/
MAC_I[i] = ((EVAL >> (56-(i*8))) ^ (z[4] >> (24-(i*8)))) & 0xff;
return MAC_I;
}

View File

@ -0,0 +1,75 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "common/task_dispatcher.h"
#include <queue>
namespace srslte {
task_dispatcher::task_dispatcher(uint32_t max_pending_tasks)
{
pthread_cond_init(&cvar, NULL);
pthread_mutex_init(&mutex, NULL);
}
task_dispatcher::~task_dispatcher()
{
running = false;
pthread_cond_signal(&cvar);
wait_thread_finish();
pthread_cond_destroy(&cvar);
pthread_mutex_destroy(&mutex);
}
void task_dispatcher::push_task(uint32_t task_code)
{
pthread_mutex_lock(&mutex);
pending_tasks.push(task_code);
pthread_cond_signal(&cvar);
pthread_mutex_unlock(&mutex);
}
void task_dispatcher::run_thread()
{
running = true;
while(running) {
uint32_t task = 0;
pthread_mutex_lock(&mutex);
while(pending_tasks.empty()) {
pthread_cond_wait(&cvar, &mutex);
}
task = (uint32_t) pending_tasks.front();
pending_tasks.pop();
pthread_mutex_unlock(&mutex);
if (running) {
run_task(task);
}
}
}
}

View File

@ -0,0 +1,289 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <assert.h>
#include <stdio.h>
#include "common/thread_pool.h"
#define DEBUG 0
#define debug_thread(fmt, ...) do { if(DEBUG) printf(fmt, __VA_ARGS__); } while(0)
#define USE_QUEUE
namespace srslte {
void thread_pool::worker::setup(uint32_t id, thread_pool *parent, uint32_t prio, uint32_t mask)
{
my_id = id;
my_parent = parent;
if(mask == 255)
{
start(prio);
}
else
{
start_cpu_mask(prio,mask);
}
}
void thread_pool::worker::run_thread()
{
running = true;
while(running) {
wait_to_start();
if (running) {
work_imp();
finished();
}
}
}
uint32_t thread_pool::worker::get_id()
{
return my_id;
}
void thread_pool::worker::stop()
{
running = false;
pthread_cond_signal(&my_parent->cvar[my_id]);
wait_thread_finish();
}
thread_pool::thread_pool(uint32_t max_workers_) :
workers(max_workers_),
status(max_workers_),
cvar(max_workers_),
mutex(max_workers_)
{
max_workers = max_workers_;
for (int i=0;i<max_workers;i++) {
workers[i] = NULL;
status[i] = IDLE;
pthread_mutex_init(&mutex[i], NULL);
pthread_cond_init(&cvar[i], NULL);
}
pthread_mutex_init(&mutex_queue, NULL);
pthread_cond_init(&cvar_queue, NULL);
running = true;
nof_workers = 0;
}
void thread_pool::init_worker(uint32_t id, worker *obj, uint32_t prio, uint32_t mask)
{
if (id < max_workers) {
if (id >= nof_workers) {
nof_workers = id+1;
}
pthread_mutex_lock(&mutex_queue);
workers[id] = obj;
available_workers.push(obj);
obj->setup(id, this, prio, mask);
pthread_cond_signal(&cvar_queue);
pthread_mutex_unlock(&mutex_queue);
}
}
void thread_pool::stop()
{
/* Stop any thread waiting for available worker */
running = false;
/* Now stop all workers */
for (uint32_t i=0;i<nof_workers;i++) {
if (workers[i]) {
workers[i]->stop();
// Need to call start to wake it up
start_worker(i);
workers[i]->wait_thread_finish();
}
pthread_cond_destroy(&cvar[i]);
pthread_mutex_destroy(&mutex[i]);
}
pthread_cond_destroy(&cvar_queue);
pthread_mutex_destroy(&mutex_queue);
}
void thread_pool::worker::release()
{
finished();
}
void thread_pool::worker::wait_to_start()
{
debug_thread("wait_to_start() id=%d, status=%d, enter\n", my_id, my_parent->status[my_id]);
pthread_mutex_lock(&my_parent->mutex[my_id]);
while(my_parent->status[my_id] != START_WORK && running) {
pthread_cond_wait(&my_parent->cvar[my_id], &my_parent->mutex[my_id]);
}
my_parent->status[my_id] = WORKING;
pthread_mutex_unlock(&my_parent->mutex[my_id]);
debug_thread("wait_to_start() id=%d, status=%d, exit\n", my_id, my_parent->status[my_id]);
}
void thread_pool::worker::finished()
{
#ifdef USE_QUEUE
pthread_mutex_lock(&my_parent->mutex[my_id]);
my_parent->status[my_id] = IDLE;
pthread_mutex_unlock(&my_parent->mutex[my_id]);
pthread_mutex_lock(&my_parent->mutex_queue);
pthread_cond_signal(&my_parent->cvar_queue);
pthread_mutex_unlock(&my_parent->mutex_queue);
#else
pthread_mutex_lock(&my_parent->mutex[my_id]);
my_parent->status[my_id] = IDLE;
pthread_cond_signal(&my_parent->cvar[my_id]);
pthread_mutex_unlock(&my_parent->mutex[my_id]);
#endif
}
thread_pool::worker* thread_pool::wait_worker()
{
return wait_worker(0);
}
bool thread_pool::find_finished_worker(uint32_t tti, uint32_t *id) {
for(int i=0;i<nof_workers;i++) {
if (status[i] == IDLE) {
*id = i;
return true;
}
}
return false;
}
thread_pool::worker* thread_pool::wait_worker(uint32_t tti)
{
thread_pool::worker *x;
#ifdef USE_QUEUE
debug_thread("wait_worker() - enter - tti=%d, state0=%d, state1=%d\n", tti, status[0], status[1]);
pthread_mutex_lock(&mutex_queue);
uint32_t id = 0;
while(!find_finished_worker(tti, &id) && running) {
pthread_cond_wait(&cvar_queue, &mutex_queue);
}
pthread_mutex_unlock(&mutex_queue);
if (running) {
x = workers[id];
pthread_mutex_lock(&mutex[id]);
status[id] = WORKER_READY;
pthread_mutex_unlock(&mutex[id]);
} else {
x = NULL;
}
debug_thread("wait_worker() - exit - id=%d\n", id);
#else
uint32_t id = tti%nof_workers;
pthread_mutex_lock(&mutex[id]);
while(status[id] != IDLE && running) {
pthread_cond_wait(&cvar[id], &mutex[id]);
}
if (running) {
x = (worker*) workers[id];
status[id] = WORKER_READY;
} else {
x = NULL;
}
pthread_mutex_unlock(&mutex[id]);
#endif
return x;
}
thread_pool::worker* thread_pool::wait_worker_nb(uint32_t tti)
{
thread_pool::worker *x;
debug_thread("wait_worker() - enter - tti=%d, state0=%d, state1=%d\n", tti, status[0], status[1]);
pthread_mutex_lock(&mutex_queue);
uint32_t id = 0;
if (find_finished_worker(tti, &id)) {
x = workers[id];
} else {
x = NULL;
}
pthread_mutex_unlock(&mutex_queue);
if (running && x) {
pthread_mutex_lock(&mutex[id]);
status[id] = WORKER_READY;
pthread_mutex_unlock(&mutex[id]);
} else {
x = NULL;
}
debug_thread("wait_worker() - exit - id=%d\n", id);
return x;
}
void thread_pool::start_worker(uint32_t id) {
if (id < nof_workers) {
pthread_mutex_lock(&mutex[id]);
status[id] = START_WORK;
pthread_cond_signal(&cvar[id]);
pthread_mutex_unlock(&mutex[id]);
debug_thread("start_worker() id=%d, status=%d\n", id, status[id]);
}
}
void thread_pool::start_worker(worker* x)
{
for (uint32_t i=0;i<nof_workers;i++) {
if (x == workers[i]) {
start_worker(i);
return;
}
}
}
thread_pool::worker* thread_pool::get_worker(uint32_t id)
{
if (id < nof_workers) {
return workers[id];
}
return NULL;
}
uint32_t thread_pool::get_nof_workers()
{
return nof_workers;
}
}

153
srslte/lib/common/threads.c Normal file
View File

@ -0,0 +1,153 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include "common/threads.h"
bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg) {
return threads_new_rt_prio(thread, start_routine, arg, -1);
}
bool threads_new_rt_prio(pthread_t *thread, void *(*start_routine) (void*), void *arg, int prio_offset) {
return threads_new_rt_cpu(thread, start_routine, arg, -1, prio_offset);
}
bool threads_new_rt_mask(pthread_t *thread, void *(*start_routine) (void*), void *arg,int mask, int prio_offset){
return threads_new_rt_cpu(thread, start_routine, arg, mask*100, prio_offset);// we multiply mask by 100 to distinguish it from a single cpu core id
}
bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu, int prio_offset) {
bool ret = false;
pthread_attr_t attr;
struct sched_param param;
cpu_set_t cpuset;
if (prio_offset >= 0) {
param.sched_priority = sched_get_priority_max(SCHED_FIFO) - prio_offset;
pthread_attr_init(&attr);
if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {
perror("pthread_attr_setinheritsched");
}
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
perror("pthread_attr_setschedpolicy");
}
if (pthread_attr_setschedparam(&attr, &param)) {
perror("pthread_attr_setschedparam");
fprintf(stderr, "Error not enough privileges to set Scheduling priority\n");
}
}
if(cpu != -1) {
if(cpu > 50) {
int mask;
mask = cpu/100;
CPU_ZERO(&cpuset);
for(int i = 0; i < 8;i++){
if(((mask >> i) & 0x01) == 1){
printf("Setting this worker with affinity to core %d\n", i);
CPU_SET((size_t) i , &cpuset);
}
}
} else {
CPU_ZERO(&cpuset);
CPU_SET((size_t) cpu, &cpuset);
printf("Setting CPU affinity to cpu_id=%d\n", cpu);
}
if(pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset)) {
perror("pthread_attr_setaffinity_np");
}
}
int err = pthread_create(thread, prio_offset >= 0 ? &attr : NULL, start_routine, arg);
if (err) {
if (EPERM == err) {
perror("Warning: Failed to create thread with real-time priority. Creating it with normal priority");
err = pthread_create(thread, NULL, start_routine, arg);
if (err) {
perror("pthread_create");
} else {
ret = true;
}
} else {
perror("pthread_create");
}
} else {
ret = true;
}
if (prio_offset >= 0) {
pthread_attr_destroy(&attr);
}
return ret;
}
void threads_print_self() {
pthread_t thread;
cpu_set_t cpuset;
struct sched_param param;
int policy;
const char *p;
int s,j;
thread = pthread_self();
s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0) {
printf("error pthread_getaffinity_np: %s\n",strerror(s));
}
printf("Set returned by pthread_getaffinity_np() contained:\n");
for (j = 0; j < CPU_SETSIZE; j++) {
if (CPU_ISSET(j, &cpuset)) {
printf(" CPU %d\n", j);
}
}
s = pthread_getschedparam(thread, &policy, &param);
if (s != 0) {
printf("error pthread_getaffinity_np: %s\n", strerror(s));
}
switch(policy) {
case SCHED_FIFO:
p = "SCHED_FIFO";
break;
case SCHED_RR:
p = "SCHED_RR";
break;
default:
p = "Other";
break;
}
printf("Sched policy is %s. Priority is %d\n",p,param.sched_priority);
}

View File

@ -0,0 +1,78 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include "common/tti_sync_cv.h"
namespace srslte {
tti_sync_cv::tti_sync_cv(uint32_t modulus): tti_sync(modulus)
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
}
tti_sync_cv::~tti_sync_cv()
{
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
}
uint32_t tti_sync_cv::wait()
{
pthread_mutex_lock(&mutex);
while(wait_condition()) {
pthread_cond_wait(&cond, &mutex);
}
uint32_t x = consumer_cntr;
increase_consumer();
pthread_mutex_unlock(&mutex);
return x;
}
void tti_sync_cv::resync()
{
consumer_cntr = producer_cntr;
}
void tti_sync_cv::set_producer_cntr(uint32_t producer_cntr)
{
pthread_mutex_lock(&mutex);
init_counters(producer_cntr);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void tti_sync_cv::increase()
{
pthread_mutex_lock(&mutex);
increase_producer();
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}

View File

@ -0,0 +1,37 @@
# Copyright 2015 Software Radio Systems Limited
#
# This file is part of srsUE
#
# srsUE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsUE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
#######################################################################
# LOGGER TEST
#######################################################################
add_executable(logger_test logger_test.cc)
target_link_libraries(logger_test srslte_phy srslte_common srslte_phy lte ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
add_test(logger_test logger_test)
add_executable(msg_queue_test msg_queue_test.cc)
target_link_libraries(msg_queue_test srslte_phy srslte_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
add_test(msg_queue_test msg_queue_test)
add_executable(log_filter_test log_filter_test.cc)
target_link_libraries(log_filter_test srslte_phy srslte_common srslte_phy lte ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
add_executable(timeout_test timeout_test.cc)
target_link_libraries(timeout_test srslte_phy ${CMAKE_THREAD_LIBS_INIT})
add_executable(bcd_helpers_test bcd_helpers_test.cc)

View File

@ -0,0 +1,67 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <assert.h>
#include "common/bcd_helpers.h"
using namespace srslte;
int main(int argc, char **argv)
{
std::string mcc_str = "001";
std::string mnc_str = "001";
uint16_t mcc;
uint16_t mnc;
// String to code
assert(string_to_mcc(mcc_str, &mcc));
assert(mcc == 0xF001);
assert(string_to_mnc(mnc_str, &mnc));
assert(mnc == 0xF001);
mnc_str = "01";
assert(string_to_mnc(mnc_str, &mnc));
assert(mnc == 0xFF01);
// Code to string
mcc_str = "";
mnc_str = "";
mcc = 0xF001;
mnc = 0xF001;
assert(mcc_to_string(mcc, &mcc_str));
assert(mcc_str.compare("001") == 0);
assert(mnc_to_string(mnc, &mnc_str));
assert(mnc_str.compare("001") == 0);
mnc = 0xFF01;
assert(mnc_to_string(mnc, &mnc_str));
assert(mnc_str.compare("01") == 0);
}

View File

@ -0,0 +1,133 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define NTHREADS 100
#define NMSGS 100
#include <stdio.h>
#include "common/log_filter.h"
using namespace srslte;
typedef struct {
logger *l;
int thread_id;
}args_t;
void* thread_loop(void *a) {
args_t *args = (args_t*)a;
char buf[100];
sprintf(buf, "LAYER%d", args->thread_id);
log_filter filter(buf, args->l);
filter.set_level(LOG_LEVEL_INFO);
for(int i=0;i<NMSGS;i++)
{
filter.error("Thread %d: %d", args->thread_id, i);
filter.warning("Thread %d: %d", args->thread_id, i);
filter.info("Thread %d: %d", args->thread_id, i);
filter.debug("Thread %d: %d", args->thread_id, i);
}
}
void* thread_loop_hex(void *a) {
args_t *args = (args_t*)a;
char buf[100];
uint8_t hex[100];
for(int i=0;i<100;i++)
hex[i] = i & 0xFF;
sprintf(buf, "LAYER%d", args->thread_id);
log_filter filter(buf, args->l);
filter.set_level(LOG_LEVEL_DEBUG);
filter.set_hex_limit(32);
for(int i=0;i<NMSGS;i++)
{
filter.error_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
filter.warning_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
filter.info_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
filter.debug_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
}
return NULL;
}
void write(std::string filename) {
logger l;
l.init(filename);
pthread_t threads[NTHREADS];
args_t args[NTHREADS];
for(int i=0;i<NTHREADS;i++) {
args[i].l = &l;
args[i].thread_id = i;
pthread_create(&threads[i], NULL, &thread_loop_hex, &args[i]);
}
for(int i=0;i<NTHREADS;i++) {
pthread_join(threads[i], NULL);
}
}
bool read(std::string filename) {
bool pass = true;
bool written[NTHREADS][NMSGS];
int thread, msg;
int r;
for(int i=0;i<NTHREADS;i++) {
for(int j=0;j<NMSGS;j++) {
written[i][j] = false;
}
}
FILE *f = fopen(filename.c_str(), "r");
if(f!=NULL) {
while(fscanf(f, "Thread %d: %d\n", &thread, &msg)) {
written[thread][msg] = true;
}
fclose(f);
}
for(int i=0;i<NTHREADS;i++) {
for(int j=0;j<NMSGS;j++) {
if(!written[i][j]) pass = false;
}
}
return pass;
}
int main(int argc, char **argv) {
bool result;
std::string f("log.txt");
write(f);
// result = read(f);
// remove(f.c_str());
// if(result) {
// printf("Passed\n");
// exit(0);
// }else{
// printf("Failed\n;");
// exit(1);
// }
}

View File

@ -0,0 +1,106 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define NTHREADS 100
#define NMSGS 100
#include <stdlib.h>
#include <stdio.h>
#include "common/logger.h"
using namespace srslte;
typedef struct {
logger *l;
int thread_id;
}args_t;
void* thread_loop(void *a) {
args_t *args = (args_t*)a;
char buf[100];
for(int i=0;i<NMSGS;i++)
{
sprintf(buf, "Thread %d: %d", args->thread_id, i);
args->l->log(buf);
}
return NULL;
}
void write(std::string filename) {
logger l;
l.init(filename);
pthread_t threads[NTHREADS];
args_t args[NTHREADS];
for(int i=0;i<NTHREADS;i++) {
args[i].l = &l;
args[i].thread_id = i;
pthread_create(&threads[i], NULL, &thread_loop, &args[i]);
}
for(int i=0;i<NTHREADS;i++) {
pthread_join(threads[i], NULL);
}
}
bool read(std::string filename) {
bool pass = true;
bool written[NTHREADS][NMSGS];
int thread, msg;
int r;
for(int i=0;i<NTHREADS;i++) {
for(int j=0;j<NMSGS;j++) {
written[i][j] = false;
}
}
FILE *f = fopen(filename.c_str(), "r");
if(f!=NULL) {
while(fscanf(f, "Thread %d: %d\n", &thread, &msg)) {
written[thread][msg] = true;
}
fclose(f);
}
for(int i=0;i<NTHREADS;i++) {
for(int j=0;j<NMSGS;j++) {
if(!written[i][j]) pass = false;
}
}
return pass;
}
int main(int argc, char **argv) {
bool result;
std::string f("log.txt");
write(f);
result = read(f);
remove(f.c_str());
if(result) {
printf("Passed\n");
exit(0);
}else{
printf("Failed\n;");
exit(1);
}
}

View File

@ -0,0 +1,81 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define NMSGS 1000000
#include <stdio.h>
#include "common/msg_queue.h"
using namespace srslte;
typedef struct {
msg_queue *q;
}args_t;
void* write_thread(void *a) {
args_t *args = (args_t*)a;
for(uint32_t i=0;i<NMSGS;i++)
{
byte_buffer_t *b = new byte_buffer_t;
memcpy(b->msg, &i, 4);
b->N_bytes = 4;
args->q->write(b);
}
return NULL;
}
int main(int argc, char **argv) {
bool result;
msg_queue q;
byte_buffer_t *b;
pthread_t thread;
args_t args;
u_int32_t r;
result = true;
args.q = &q;
pthread_create(&thread, NULL, &write_thread, &args);
for(uint32_t i=0;i<NMSGS;i++)
{
q.read(&b);
memcpy(&r, b->msg, 4);
delete b;
if(r != i)
result = false;
}
pthread_join(thread, NULL);
if(result) {
printf("Passed\n");
exit(0);
}else{
printf("Failed\n;");
exit(1);
}
}

View File

@ -0,0 +1,92 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include <stdio.h>
#include "common/timeout.h"
using namespace srslte;
class callback
: public timeout_callback
{
public:
callback() {
finished = false;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cvar, NULL);
}
void timeout_expired(uint32_t timeout_id)
{
pthread_mutex_lock(&mutex);
finished = true;
pthread_cond_signal(&cvar);
pthread_mutex_unlock(&mutex);
}
void wait()
{
pthread_mutex_lock(&mutex);
while(!finished) {
pthread_cond_wait(&cvar, &mutex);
}
pthread_mutex_unlock(&mutex);
}
struct timeval start_time[3];
private:
bool finished;
pthread_cond_t cvar;
pthread_mutex_t mutex;
};
int main(int argc, char **argv) {
bool result;
uint32_t id = 0;
uint32_t duration_msec = 5;
callback c;
timeout t;
gettimeofday(&c.start_time[1], NULL);
t.start(duration_msec, 0, &c);
c.wait();
gettimeofday(&c.start_time[2], NULL);
get_time_interval(c.start_time);
uint32_t diff_ms = c.start_time[0].tv_usec*1e-3;
printf("Target duration: %dms, started: %ld:%ld, ended: %ld:%ld, actual duration %dms\n",
duration_msec, c.start_time[1].tv_sec, c.start_time[1].tv_usec, c.start_time[2].tv_sec, c.start_time[2].tv_usec, diff_ms);
result = (diff_ms == duration_msec);
if(result) {
printf("Passed\n");
exit(0);
}else{
printf("Failed\n;");
exit(1);
}
}