Merge branch 'next' into mobility

This commit is contained in:
Ismael Gomez 2017-11-24 12:02:41 +01:00
commit d428760b20
80 changed files with 1947 additions and 808 deletions

View File

@ -55,6 +55,12 @@ if(NOT CMAKE_BUILD_TYPE)
endif(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
# Generate CMake to include build information
configure_file(
${CMAKE_SOURCE_DIR}/cmake/modules/SRSLTEbuildinfo.cmake.in
${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake
)
########################################################################
# Options
########################################################################

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.6)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@"
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@"
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "Generating build_info.h")
configure_file(
@CMAKE_SOURCE_DIR@/lib/include/srslte/build_info.h.in
@CMAKE_BINARY_DIR@/lib/include/srslte/build_info.h
)

View File

@ -163,6 +163,8 @@ int main(int argc, char **argv) {
float cfo = 0;
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
srslte_debug_handle_crash(argc, argv);
if (parse_args(&prog_args, argc, argv)) {
exit(-1);
}

View File

@ -153,6 +153,8 @@ int main(int argc, char **argv) {
uint32_t freq;
uint32_t n_found_cells=0;
srslte_debug_handle_crash(argc, argv);
parse_args(argc, argv);
printf("Opening RF device...\n");

View File

@ -701,6 +701,8 @@ int main(int argc, char **argv) {
srslte_refsignal_t csr_refs;
srslte_refsignal_t mbsfn_refs;
srslte_debug_handle_crash(argc, argv);
#ifdef DISABLE_RF
if (argc < 3) {
usage(argv[0]);

View File

@ -326,7 +326,8 @@ srslte_netsink_t net_sink, net_sink_signal;
#define PRINT_LINE_ADVANCE_CURSOR() printf("\033[%dB", prev_nof_lines + 1)
int main(int argc, char **argv) {
int ret;
struct timeval t[3];
int ret;
int decimate = 1;
srslte_cell_t cell;
int64_t sf_cnt;
@ -340,6 +341,8 @@ int main(int argc, char **argv) {
int sfn_offset;
float cfo = 0;
srslte_debug_handle_crash(argc, argv);
parse_args(&prog_args, argc, argv);
for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) {
@ -559,7 +562,7 @@ int main(int argc, char **argv) {
// Variables for measurements
uint32_t nframes=0;
uint8_t ri = 0, pmi = 0;
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0,
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, procrate = 0.0,
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
bool decode_pdsch = false;
@ -655,6 +658,7 @@ int main(int argc, char **argv) {
decode_pdsch = false;
}
}
gettimeofday(&t[1], NULL);
if (decode_pdsch) {
if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe
if (cell.nof_ports == 1) {
@ -690,6 +694,8 @@ int main(int argc, char **argv) {
INFO("mbsfn PDU size is %d\n", n);
}
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (n < 0) {
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
@ -723,16 +729,19 @@ int main(int argc, char **argv) {
}
nof_trials++;
nof_trials++;
uint32_t nof_bits = ((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0));
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f);
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f);
enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA(((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0))/1000.0f, uerate, 0.01f);
enodebrate = SRSLTE_VEC_EMA(nof_bits/1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA(nof_bits/1000.0f, uerate, 0.001f);
float elapsed = (float) t[0].tv_usec + t[0].tv_sec*1.0e+6f;
if (elapsed != 0.0f) {
procrate = SRSLTE_VEC_EMA(nof_bits/elapsed, procrate, 0.01f);
}
nframes++;
if (isnan(rsrq)) {
@ -769,7 +778,7 @@ int main(int argc, char **argv) {
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate);
PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials));
PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float) 100 * ue_dl.pdsch_pkt_errors / ue_dl.pdsch_pkts_total);
if(prog_args.mbsfn_area_id > -1){

View File

@ -2721,6 +2721,10 @@ typedef struct{
// Functions
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req,
LIBLTE_BYTE_MSG_STRUCT *msg);
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req,
uint8 sec_hdr_type,
uint32 count,
LIBLTE_BYTE_MSG_STRUCT *msg);
LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg,
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req);

View File

@ -3930,7 +3930,7 @@ typedef enum{
}LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM;
static const char liblte_rrc_pdsch_config_p_a_text[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS][20] = { "-6", "-4.77", "-3", "-1.77",
"0", "1", "2", "3"};
static const double liblte_rrc_pdsch_config_p_a_num[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS] = {-6, -4.77, -3, -1.77, 0, 1, 2, 3};
static const float liblte_rrc_pdsch_config_p_a_num[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS] = {-6, -4.77f, -3, -1.77f, 0, 1, 2, 3};
// Structs
// PDSCH Config Common struct defined above
// Functions

View File

@ -0,0 +1,56 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* 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/.
*
*/
#ifndef BUILD_INFO_
#define BUILD_INFO_
# ifdef __cplusplus
extern "C" {
# endif
#ifdef NDEBUG
static char build_mode[] = "Release";
#else
static char build_mode[] = "Debug";
#endif
// the configured build options for srsLTE
static char build_info[] = "commit @GIT_COMMIT_HASH@ on branch @GIT_BRANCH@";
SRSLTE_API char* srslte_get_build_info() {
return build_info;
};
SRSLTE_API char* srslte_get_build_mode() {
return build_mode;
}
# ifdef __cplusplus
}
# endif
#endif // BUILD_INFO_

View File

@ -123,8 +123,6 @@ public:
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;

View File

@ -46,9 +46,12 @@
#define HARQ_DELAY_MS 4
#define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS
#define TTI_RX(tti) (tti>HARQ_DELAY_MS?((tti-HARQ_DELAY_MS)%10240):(10240+tti-HARQ_DELAY_MS))
#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
#define UL_PIDOF(tti) (tti%(2*HARQ_DELAY_MS))
#define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20)
#define TTIMOD(tti) (tti%TTIMOD_SZ)

View File

@ -52,16 +52,20 @@ class ue_interface
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 int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0;
virtual std::string get_imsi_str() = 0;
virtual std::string get_imei_str() = 0;
virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
virtual bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 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 *res,
uint8_t *k_asme) = 0;
virtual void generate_nas_keys(uint8_t *k_asme,
uint8_t *k_nas_enc,
uint8_t *k_nas_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
@ -71,7 +75,8 @@ public:
class usim_interface_rrc
{
public:
virtual void generate_as_keys(uint32_t count_ul,
virtual void generate_as_keys(uint8_t *k_asme,
uint32_t count_ul,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -112,6 +117,7 @@ public:
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;
virtual bool get_k_asme(uint8_t *k_asme_, uint32_t n) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
virtual void plmn_search_end() = 0;
};

View File

@ -49,18 +49,21 @@
*/
SRSLTE_API int srslte_precoding_single(cf_t *x,
cf_t *y,
int nof_symbols);
int nof_symbols,
float scaling);
SRSLTE_API int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS],
cf_t *y[SRSLTE_MAX_PORTS],
int nof_ports,
int nof_symbols);
int nof_symbols,
float scaling);
SRSLTE_API int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS],
cf_t *y[SRSLTE_MAX_PORTS],
int nof_layers,
int nof_ports,
int nof_symbols);
int nof_symbols,
float scaling);
SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
cf_t *y[SRSLTE_MAX_PORTS],
@ -68,6 +71,7 @@ SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
int nof_ports,
int codebook_idx,
int nof_symbols,
float scaling,
srslte_mimo_type_t type);
/* Estimates the vector "x" based on the received signal "y" and the channel estimates "h"
@ -76,6 +80,7 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y,
cf_t *h,
cf_t *x,
int nof_symbols,
float scaling,
float noise_estimate);
SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS],
@ -83,42 +88,37 @@ SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *x,
int nof_rxant,
int nof_symbols,
float scaling,
float noise_estimate);
SRSLTE_API int srslte_predecoding_diversity(cf_t *y,
cf_t *h[SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_ports,
int nof_symbols);
int nof_symbols,
float scaling);
SRSLTE_API int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_rxant,
int nof_ports,
int nof_symbols);
SRSLTE_API int srslte_predecoding_type(cf_t *y,
cf_t *h[SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_ports,
int nof_layers,
int nof_symbols,
srslte_mimo_type_t type,
float noise_estimate);
int nof_symbols,
float scaling);
SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder);
SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_rxant,
int nof_ports,
int nof_layers,
int codebook_idx,
int nof_symbols,
srslte_mimo_type_t type,
float noise_estimate);
SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_rxant,
int nof_ports,
int nof_layers,
int codebook_idx,
int nof_symbols,
srslte_mimo_type_t type,
float scaling,
float noise_estimate);
SRSLTE_API int srslte_precoding_pmi_select(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_symbols,

View File

@ -65,6 +65,9 @@ typedef struct SRSLTE_API {
uint16_t ue_rnti;
bool is_ue;
/* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */
float rho_a;
/* buffers */
// void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
@ -101,6 +104,9 @@ SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q,
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti);
SRSLTE_API void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q,
float rho_a);
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
uint16_t rnti);

View File

@ -39,6 +39,13 @@
#include "srslte/phy/fec/softbuffer.h"
#include "srslte/phy/fec/cbsegm.h"
/* 3GPP 36.213 Table 5.2-1: The cell-specific ratio rho_B / rho_A for 1, 2, or 4 cell specific antenna ports */
static const float pdsch_cfg_cell_specific_ratio_table[2][4] =
{ /* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f},
/* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f}
};
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm[SRSLTE_MAX_CODEWORDS];
srslte_ra_dl_grant_t grant;

View File

@ -38,10 +38,13 @@
#define RESAMPLE_ARB_
#include <stdint.h>
#include <stdbool.h>
#include <complex.h>
#include "srslte/config.h"
#define SRSLTE_RESAMPLE_ARB_N_35 35
#define SRSLTE_RESAMPLE_ARB_N 32 // Polyphase filter rows
#define SRSLTE_RESAMPLE_ARB_M 8 // Polyphase filter columns
@ -49,11 +52,13 @@ typedef struct SRSLTE_API {
float rate; // Resample rate
float step; // Step increment through filter
float acc; // Index into filter
bool interpolate;
cf_t reg[SRSLTE_RESAMPLE_ARB_M]; // Our window of samples
} srslte_resample_arb_t;
SRSLTE_API void srslte_resample_arb_init(srslte_resample_arb_t *q,
float rate);
float rate, bool interpolate);
SRSLTE_API int srslte_resample_arb_compute(srslte_resample_arb_t *q,
cf_t *input,

View File

@ -139,6 +139,10 @@ SRSLTE_API srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q,
uint32_t find_offset,
uint32_t *peak_position);
SRSLTE_API float srslte_sync_cfo_estimate(srslte_sync_t *q,
cf_t *input,
int find_offset);
/* Estimates the CP length */
SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q,
cf_t *input,

View File

@ -104,6 +104,9 @@ typedef struct SRSLTE_API {
uint32_t pmi[SRSLTE_MAX_LAYERS];
uint32_t ri;
/* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */
float rho_b;
srslte_dci_format_t dci_format;
uint64_t pkt_errors;
uint64_t pkts_total;
@ -244,6 +247,9 @@ SRSLTE_API int srslte_ue_dl_set_mbsfn_area_id(srslte_ue_dl_t *q,
SRSLTE_API void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q,
uint8_t non_mbsfn_region_length);
SRSLTE_API void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q,
float rho_a,
float rho_b);
SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q,

View File

@ -88,7 +88,12 @@ typedef struct SRSLTE_API {
bool file_mode;
float file_cfo;
srslte_cfo_t file_cfo_correct;
bool mean_cfo_isunset;
float cfo;
float mean_cfo;
float cfo_ema_alpha;
srslte_ue_sync_state_t state;
uint32_t frame_len;

View File

@ -70,4 +70,6 @@ SRSLTE_API extern int srslte_verbose;
#define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__)
#endif /* CMAKE_BUILD_TYPE==Debug */
void srslte_debug_handle_crash(int argc, char **argv);
#endif // DEBUG_H

View File

@ -449,7 +449,12 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) {
#ifdef HAVE_NEON
float32x4_t sqrt_reciprocal = vrsqrteq_f32(a);
sqrt_reciprocal = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a,sqrt_reciprocal), sqrt_reciprocal),sqrt_reciprocal);
return vmulq_f32(a,sqrt_reciprocal);
float32x4_t result = vmulq_f32(a,sqrt_reciprocal);
/* Detect zeros in NEON 1/sqrtf for preventing NaN */
float32x4_t zeros = vmovq_n_f32(0); /* Zero vector */
uint32x4_t mask = vceqq_f32(a, zeros); /* Zero vector mask */
return vbslq_f32(mask, zeros, result); /* Force zero results and return */
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */

View File

@ -1411,9 +1411,9 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_eps_mobile_id_ie(LIBLTE_MME_EPS_MOBILE_ID_STRU
**ie_ptr = (((eps_mobile_id->guti.mnc/10) % 10) << 4) | ((eps_mobile_id->guti.mnc/100) % 10);
*ie_ptr += 1;
}
**ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0x0F;
**ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0xFF;
*ie_ptr += 1;
**ie_ptr = eps_mobile_id->guti.mme_group_id & 0x0F;
**ie_ptr = eps_mobile_id->guti.mme_group_id & 0xFF;
*ie_ptr += 1;
**ie_ptr = eps_mobile_id->guti.mme_code;
*ie_ptr += 1;
@ -5518,6 +5518,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_reject_msg(LIBLTE_BYTE_MSG_STRUCT
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req,
LIBLTE_BYTE_MSG_STRUCT *msg)
{
return liblte_mme_pack_attach_request_msg(attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, msg);
}
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req,
uint8 sec_hdr_type,
uint32 count,
LIBLTE_BYTE_MSG_STRUCT *msg)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 *msg_ptr = msg->msg;
@ -5525,6 +5533,20 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_M
if(attach_req != NULL &&
msg != NULL)
{
if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type)
{
// Protocol Discriminator and Security Header Type
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg_ptr++;
// MAC will be filled in later
msg_ptr += 4;
// Sequence Number
*msg_ptr = count & 0xFF;
msg_ptr++;
}
// Protocol Discriminator and Security Header Type
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg_ptr++;

View File

@ -22,7 +22,9 @@ file(GLOB CXX_SOURCES "*.cc")
file(GLOB C_SOURCES "*.c")
add_library(srslte_common STATIC ${C_SOURCES} ${CXX_SOURCES})
add_custom_target(gen_build_info COMMAND cmake -P ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake)
add_dependencies(srslte_common gen_build_info)
target_include_directories(srslte_common PUBLIC ${SEC_INCLUDE_DIRS})
target_link_libraries(srslte_common ${SEC_LIBRARIES})
install(TARGETS srslte_common DESTINATION ${LIBRARY_DIR})

View File

@ -117,7 +117,7 @@ void srslte_agc_lock(srslte_agc_t *q, bool enable) {
void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
if (!q->lock) {
float gain_db = 10*log10(q->gain);
float gain_uhd_db = 1.0;
float gain_uhd_db = 50.0;
//float gain_uhd = 1.0;
float y = 0;
// Apply current gain to input signal
@ -125,12 +125,12 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
srslte_vec_sc_prod_cfc(signal, q->gain, signal, len);
} else {
if (gain_db < 0) {
gain_db = 0.0;
gain_db = 5.0;
}
if (isinf(gain_db) || isnan(gain_db)) {
gain_db = 10.0;
gain_db = 40.0;
} else {
gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db);
gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db);
q->gain = pow(10, gain_uhd_db/10);
}
}
@ -166,7 +166,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
}
}
double gg = 1.0;
double gg = 1.0;
if (q->isfirst) {
q->y_out = y;
q->isfirst = false;
@ -177,7 +177,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target));
q->gain *= gg;
}
DEBUG("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg);
DEBUG("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg);
}
}
}

View File

@ -173,7 +173,7 @@ int main(int argc, char **argv) {
gettimeofday(&t[1], NULL);
for (int j=0;j<100;j++) {
srslte_predecoding_single(input, ce, output, num_re, 0);
srslte_predecoding_single(input, ce, output, num_re, 1.0f, 0);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
@ -188,7 +188,7 @@ int main(int argc, char **argv) {
gettimeofday(&t[1], NULL);
for (int j=0;j<100;j++) {
srslte_predecoding_single(input, ce, output, num_re, srslte_chest_dl_get_noise_estimate(&est));
srslte_predecoding_single(input, ce, output, num_re, 1.0f, srslte_chest_dl_get_noise_estimate(&est));
}
gettimeofday(&t[2], NULL);
get_time_interval(t);

File diff suppressed because it is too large Load Diff

View File

@ -44,14 +44,16 @@ int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1;
char *mimo_type_name = NULL;
char decoder_type_name [16] = "zf";
float snr_db = 100.0f;
float scaling = 0.1f;
void usage(char *prog) {
printf(
"Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n"
" -r [nof_rx_ports]\n", prog);
" -r [nof_rx_ports] -g [scaling]\n", prog);
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
printf("\t-c codebook_idx [Default %d]\n", codebook_idx);
printf("\t-s SNR in dB [Default %.1fdB]*\n", snr_db);
printf("\t-g Scaling [Default %.1f]*\n", scaling);
printf("\t-d decoder type [zf|mmse] [Default %s]\n", decoder_type_name);
printf("\n");
printf("* Performance test example:\n\t for snr in {0..20..1}; do ./precoding_test -m single -s $snr; done; \n\n", decoder_type_name);
@ -59,7 +61,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "mplnrcds")) != -1) {
while ((opt = getopt(argc, argv, "mplnrcdsg")) != -1) {
switch (opt) {
case 'n':
nof_symbols = atoi(argv[optind]);
@ -85,6 +87,9 @@ void parse_args(int argc, char **argv) {
case 's':
snr_db = (float) atof(argv[optind]);
break;
case 'g':
scaling = (float) atof(argv[optind]);
break;
default:
usage(argv[0]);
exit(-1);
@ -149,7 +154,7 @@ void populate_channel(srslte_mimo_type_t type, cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_
static void awgn(cf_t *y[SRSLTE_MAX_PORTS], uint32_t n, float snr) {
int i;
float std_dev = powf(10, - (snr + 3.0f) / 20.0f);
float std_dev = powf(10, - (snr + 3.0f) / 20.0f) * scaling;
for (i = 0; i < nof_rx_ports; i++) {
srslte_ch_awgn_c(y[i], y[i], std_dev, n);
@ -250,7 +255,7 @@ int main(int argc, char **argv) {
}
/* Execute Precoding (Tx) */
if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, codebook_idx, nof_symbols, type) < 0) {
if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, codebook_idx, nof_symbols, scaling, type) < 0) {
fprintf(stderr, "Error layer mapper encoder\n");
exit(-1);
}
@ -285,8 +290,8 @@ int main(int argc, char **argv) {
/* predecoding / equalization */
struct timeval t[3];
gettimeofday(&t[1], NULL);
srslte_predecoding_type_multi(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers,
codebook_idx, nof_re, type, powf(10, -snr_db/10));
srslte_predecoding_type(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers,
codebook_idx, nof_re, type, scaling, powf(10, -snr_db / 10));
gettimeofday(&t[2], NULL);
get_time_interval(t);

View File

@ -497,10 +497,10 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
/* in control channels, only diversity is supported */
if (nant == 1) {
/* no need for layer demapping */
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate);
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, 1.0f, noise_estimate);
} else {
srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant,
q->nof_symbols);
q->nof_symbols, 1.0f);
srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant);
}
@ -591,7 +591,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
q->nof_symbols / q->cell.nof_ports);
q->nof_symbols / q->cell.nof_ports, 1.0f);
} else {
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
}

View File

@ -219,9 +219,9 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P
/* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, q->nof_rx_antennas, q->nof_symbols, noise_estimate);
srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate);
} else {
srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols);
srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f);
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports);
}
@ -278,7 +278,7 @@ int srslte_pcfich_encode(srslte_pcfich_t *q, uint32_t cfi, cf_t *slot_symbols[SR
/* layer mapping & precoding */
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
srslte_precoding_diversity(x, q_symbols, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports);
srslte_precoding_diversity(x, q_symbols, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports, 1.0f);
} else {
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
}

View File

@ -485,9 +485,9 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA
/* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, noise_estimate/2);
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2);
} else {
srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols);
srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f);
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
}
@ -618,7 +618,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
/* layer mapping & precoding */
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, nof_symbols);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports, 1.0f);
} else {
memcpy(q->symbols[0], q->d, nof_symbols * sizeof(cf_t));
}

View File

@ -386,6 +386,12 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
return SRSLTE_SUCCESS;
}
void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q, float rho_a) {
if (q) {
q->rho_a = rho_a;
}
}
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
@ -680,9 +686,14 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
}
float pdsch_scaling = 1.0f;
if (q->rho_a != 0.0f) {
pdsch_scaling = q->rho_a;
}
// Pre-decoder
if (srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate)<0) {
if (srslte_predecoding_type(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) {
return -1;
}
@ -822,7 +833,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
/* Precode */
srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx,
nof_symbols, cfg->mimo_type);
nof_symbols, 1.0f, cfg->mimo_type);
} else {
memcpy(q->symbols[0], q->d[0], cfg->nbits[0].nof_re * sizeof(cf_t));
}

View File

@ -239,9 +239,9 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS],
/* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, noise_estimate);
srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate);
} else {
srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB);
srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f);
srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports);
}
DEBUG("Recv!!: \n", 0);
@ -405,7 +405,7 @@ int srslte_phich_encode(srslte_phich_t *q, uint8_t ack, uint32_t ngroup, uint32_
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d0, x, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB);
srslte_precoding_diversity(x, symbols_precoding, q->cell.nof_ports,
SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports);
SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports, 1.0f);
/**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */
} else {
memcpy(q->sf_symbols[0], q->d0, SRSLTE_PHICH_MAX_NSYMB * sizeof(cf_t));

View File

@ -378,7 +378,7 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q,
}
// No tx diversity in MBSFN
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate);
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate);
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE subframe.dat: received subframe symbols\n");

View File

@ -787,7 +787,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
}
// Equalization
srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, noise_estimate);
srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, 1.0f, noise_estimate);
// Perform ML-decoding
float corr=0, corr_max=-1e9;

View File

@ -596,7 +596,7 @@ int srslte_pusch_decode(srslte_pusch_t *q,
}
// Equalization
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate);
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, 1.0f, noise_estimate);
// DFT predecoding
srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb);

View File

@ -590,11 +590,12 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
ret = dl_dci_to_grant_mcs(dci, grant, crc_is_crnti);
if (ret == SRSLTE_SUCCESS) {
// Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0
if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END &&
dci->dci_is_1c)
{
dci->rv_idx = 0;
}
if (dci->dci_is_1c) {
if ((msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END) || msg_rnti == SRSLTE_PRNTI)
{
dci->rv_idx = 0;
}
}
} else {
return SRSLTE_ERROR;
}

View File

@ -53,7 +53,7 @@ srslte_cell_t cell = {
char mimo_type_str [32] = "single";
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
uint32_t cfi = 2;
uint32_t cfi = 1;
uint32_t mcs[SRSLTE_MAX_CODEWORDS] = {0, 0};
uint32_t subframe = 1;
int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1};
@ -496,7 +496,9 @@ int main(int argc, char **argv) {
if (grant.tb_en[tb]) {
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
if (data_tx[tb][byte] != data_rx[tb][byte]) {
ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]);
ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quiting...", byte, tb, data_tx[tb][byte], data_rx[tb][byte]);
printf("Tx: "); srslte_vec_fprint_byte(stdout, data_tx[tb], grant.mcs[tb].tbs / 8);
printf("Rx: "); srslte_vec_fprint_byte(stdout, data_rx[tb], grant.mcs[tb].tbs / 8);
ret = SRSLTE_ERROR;
goto quit;
}

View File

@ -28,64 +28,104 @@
#include <string.h>
#include "srslte/phy/resampling/resample_arb.h"
#include "srslte/phy/utils/debug.h"
float srslte_resample_arb_polyfilt[SRSLTE_RESAMPLE_ARB_N][SRSLTE_RESAMPLE_ARB_M] =
{{0,0.002400347599485495,-0.006922416132556366,0.0179104136912176,0.99453086623794,-0.008521087756729117,0.0008598969867484128,0.0004992625165376107},
{-0.001903604727400391,0.004479591950094871,-0.01525319260830623,0.04647449496926549,0.9910477342662829,-0.03275243420114668,0.008048813755373533,-0.001216900416836847},
{-0.001750442300940216,0.006728826416921727,-0.02407540632178267,0.07708575473589654,0.9841056525667189,-0.05473739187922162,0.01460652754040275,-0.002745266140572769},
{-0.001807302702047332,0.009130494591071001,-0.03332524241797466,0.1096377743266821,0.9737536341125557,-0.07444712408657775,0.0205085154280773,-0.004077596041064956},
{-0.002005048395707184,0.01166717081713966,-0.04292591596219218,0.1440068251440274,0.9600641782991848,-0.09187282739868929,0.02573649090563353,-0.005218582609802016},
{-0.002303606593778858,0.01431549924598744,-0.05279365431190471,0.1800496557331084,0.9431333663677619,-0.107022659158021,0.03028295984887362,-0.006178495199082676},
{-0.002673824939871474,0.01705308556587308,-0.06283262272105428,0.2176066284621515,0.9230793648715676,-0.1199244901666642,0.03414559686566755,-0.006951034565279722},
{-0.003099294850834212,0.01985022208215894,-0.07294100481214681,0.2564996326404178,0.9000412628278351,-0.1306207218667012,0.03733448898243594,-0.007554128492547957},
{-0.003564415127592977,0.02267702927238637,-0.08300660359189582,0.2965368855416621,0.874178327911914,-0.1391710078036285,0.03986356581130199,-0.007992692892036229},
{-0.004060222849803048,0.02549633298710617,-0.09291211362877161,0.3375102453232687,0.8456688916962831,-0.1456479420005528,0.04175429631970297,-0.00827816851803391},
{-0.004574770330592958,0.02827133859849648,-0.1025308044303699,0.379200979038518,0.8147072909915275,-0.1501397816831265,0.04303284689167361,-0.008423951215857236},
{-0.005100453570725489,0.0309593063669097,-0.1117325201826136,0.4213772298764557,0.7815036335229155,-0.1527444636485677,0.0437349357738538,-0.008441129184587313},
{-0.005625340687997995,0.03351877124912608,-0.1203802123857154,0.463798444519773,0.7462810500374923,-0.1535722712206338,0.04389261707032224,-0.008345136869130621},
{-0.006140888413286479,0.03590276234084221,-0.1283350405000867,0.5062161107254219,0.7092744343987509,-0.152741400055636,0.04355110899623683,-0.008147838953503964},
{-0.006634012711933725,0.03806645580467819,-0.1354549138065051,0.5483763739419955,0.6707272107491931,-0.1503798528838644,0.0427502160096194,-0.007865132034489236},
{-0.007094909626785393,0.03996043743797257,-0.1415969539549883,0.5900207719663111,0.6308907308946271,-0.1466186670140106,0.04153829696698895,-0.007508971112586246},
{-0.007508971112586246,0.04153829696698895,-0.1466186670140106,0.6308907308946271,0.5900207719663111,-0.1415969539549883,0.03996043743797257,-0.007094909626785393},
{-0.007865132034489236,0.0427502160096194,-0.1503798528838644,0.6707272107491931,0.5483763739419955,-0.1354549138065051,0.03806645580467819,-0.006634012711933725},
{-0.008147838953503964,0.04355110899623683,-0.152741400055636,0.7092744343987509,0.5062161107254219,-0.1283350405000867,0.03590276234084221,-0.006140888413286479},
{-0.008345136869130621,0.04389261707032224,-0.1535722712206338,0.7462810500374923,0.463798444519773,-0.1203802123857154,0.03351877124912608,-0.005625340687997995},
{-0.008441129184587313,0.0437349357738538,-0.1527444636485677,0.7815036335229155,0.4213772298764557,-0.1117325201826136,0.0309593063669097,-0.005100453570725489},
{-0.008423951215857236,0.04303284689167361,-0.1501397816831265,0.8147072909915275,0.379200979038518,-0.1025308044303699,0.02827133859849648,-0.004574770330592958},
{-0.00827816851803391,0.04175429631970297,-0.1456479420005528,0.8456688916962831,0.3375102453232687,-0.09291211362877161,0.02549633298710617,-0.004060222849803048},
{-0.007992692892036229,0.03986356581130199,-0.1391710078036285,0.874178327911914,0.2965368855416621,-0.08300660359189582,0.02267702927238637,-0.003564415127592977},
{-0.007554128492547957,0.03733448898243594,-0.1306207218667012,0.9000412628278351,0.2564996326404178,-0.07294100481214681,0.01985022208215894,-0.003099294850834212},
{-0.006951034565279722,0.03414559686566755,-0.1199244901666642,0.9230793648715676,0.2176066284621515,-0.06283262272105428,0.01705308556587308,-0.002673824939871474},
{-0.006178495199082676,0.03028295984887362,-0.107022659158021,0.9431333663677619,0.1800496557331084,-0.05279365431190471,0.01431549924598744,-0.002303606593778858},
{-0.005218582609802016,0.02573649090563353,-0.09187282739868929,0.9600641782991848,0.1440068251440274,-0.04292591596219218,0.01166717081713966,-0.002005048395707184},
{-0.004077596041064956,0.0205085154280773,-0.07444712408657775,0.9737536341125557,0.1096377743266821,-0.03332524241797466,0.009130494591071001,-0.001807302702047332},
{-0.002745266140572769,0.01460652754040275,-0.05473739187922162,0.9841056525667189,0.07708575473589654,-0.02407540632178267,0.006728826416921727,-0.001750442300940216},
{-0.001216900416836847,0.008048813755373533,-0.03275243420114668,0.9910477342662829,0.04647449496926549,-0.01525319260830623,0.004479591950094871,-0.001903604727400391},
{0.0004992625165376107,0.0008598969867484128,-0.008521087756729117,0.99453086623794,0.0179104136912176,-0.006922416132556366,0.002400347599485495,0}};
#include "srslte/phy/utils/vector.h"
// TODO: use lte/utils/vector.h and Volk
cf_t srslte_resample_arb_dot_prod(cf_t* x, float *y, int len)
{
cf_t res = 0+0*I;
for(int i=0;i<len;i++){
res += x[i]*y[i];
}
return res;
float srslte_resample_arb_polyfilt[SRSLTE_RESAMPLE_ARB_N][SRSLTE_RESAMPLE_ARB_M] __attribute__((aligned(256))) =
{{0.000499262532685, 0.000859897001646, -0.008521087467670, 0.994530856609344, 0.017910413444042, -0.006922415923327, 0.002400347497314, 0.000000000000000 },
{-0.001216900418513, 0.008048813790083, -0.032752435654402, 0.991047739982605, 0.046474494040012, -0.015253192745149, 0.004479591734707, -0.001903604716063 },
{-0.002745266072452, 0.014606527984142, -0.054737392812967, 0.984105646610260, 0.077085755765438, -0.024075405672193, 0.006728826556355, -0.001750442315824 },
{-0.004077596124262, 0.020508514717221, -0.074447125196457, 0.973753631114960, 0.109637774527073, -0.033325243741274, 0.009130494669080, -0.001807302702218 },
{-0.005218582693487, 0.025736490264535, -0.091872826218605, 0.960064172744751, 0.144006818532944, -0.042925916612148, 0.011667170561850, -0.002005048329011 },
{-0.006178495008498, 0.030282959342003, -0.107022657990456, 0.943133354187012, 0.180049657821655, -0.052793655544519, 0.014315498992801, -0.002303606597707 },
{-0.006951034534723, 0.034145597368479, -0.119924493134022, 0.923079371452332, 0.217606633901596, -0.062832623720169, 0.017053086310625, -0.002673825016245 },
{-0.007554128300399, 0.037334490567446, -0.130620718002319, 0.900041282176971, 0.256499618291855, -0.072941005229950, 0.019850222393870, -0.003099294845015 },
{-0.007992693223059, 0.039863564074039, -0.139171004295349, 0.874178349971771, 0.296536892652512, -0.083006605505943, 0.022677028551698, -0.003564415033907 },
{-0.008278168737888, 0.041754297912121, -0.145647943019867, 0.845668911933899, 0.337510257959366, -0.092912115156651, 0.025496333837509, -0.004060222767293 },
{-0.008423951454461, 0.043032847344875, -0.150139778852463, 0.814707279205322, 0.379200965166092, -0.102530807256699, 0.028271337971091, -0.004574770107865 },
{-0.008441128768027, 0.043734934180975, -0.152744457125664, 0.781503617763519, 0.421377241611481, -0.111732520163059, 0.030959306284785, -0.005100453738123 },
{-0.008345136418939, 0.043892618268728, -0.153572276234627, 0.746281027793884, 0.463798433542252, -0.120380215346813, 0.033518772572279, -0.005625340621918 },
{-0.008147838525474, 0.043551109731197, -0.152741402387619, 0.709274411201477, 0.506216108798981, -0.128335043787956, 0.035902760922909, -0.006140888202935 },
{-0.007865131832659, 0.042750217020512, -0.150379851460457, 0.670727193355560, 0.548376381397247, -0.135454908013344, 0.038066454231739, -0.006634012795985 },
{-0.007508971262723, 0.041538298130035, -0.146618664264679, 0.630890727043152, 0.590020775794983, -0.141596958041191, 0.039960436522961, -0.007094909437001 },
{-0.007094909437001, 0.039960436522961, -0.141596958041191, 0.590020775794983, 0.630890727043152, -0.146618664264679, 0.041538298130035, -0.007508971262723 },
{-0.006634012795985, 0.038066454231739, -0.135454908013344, 0.548376381397247, 0.670727193355560, -0.150379851460457, 0.042750217020512, -0.007865131832659 },
{-0.006140888202935, 0.035902760922909, -0.128335043787956, 0.506216108798981, 0.709274411201477, -0.152741402387619, 0.043551109731197, -0.008147838525474 },
{-0.005625340621918, 0.033518772572279, -0.120380215346813, 0.463798433542252, 0.746281027793884, -0.153572276234627, 0.043892618268728, -0.008345136418939 },
{-0.005100453738123, 0.030959306284785, -0.111732520163059, 0.421377241611481, 0.781503617763519, -0.152744457125664, 0.043734934180975, -0.008441128768027 },
{-0.004574770107865, 0.028271337971091, -0.102530807256699, 0.379200965166092, 0.814707279205322, -0.150139778852463, 0.043032847344875, -0.008423951454461 },
{-0.004060222767293, 0.025496333837509, -0.092912115156651, 0.337510257959366, 0.845668911933899, -0.145647943019867, 0.041754297912121, -0.008278168737888 },
{-0.003564415033907, 0.022677028551698, -0.083006605505943, 0.296536892652512, 0.874178349971771, -0.139171004295349, 0.039863564074039, -0.007992693223059 },
{-0.003099294845015, 0.019850222393870, -0.072941005229950, 0.256499618291855, 0.900041282176971, -0.130620718002319, 0.037334490567446, -0.007554128300399 },
{-0.002673825016245, 0.017053086310625, -0.062832623720169, 0.217606633901596, 0.923079371452332, -0.119924493134022, 0.034145597368479, -0.006951034534723 },
{-0.002303606597707, 0.014315498992801, -0.052793655544519, 0.180049657821655, 0.943133354187012, -0.107022657990456, 0.030282959342003, -0.006178495008498 },
{-0.002005048329011, 0.011667170561850, -0.042925916612148, 0.144006818532944, 0.960064172744751, -0.091872826218605, 0.025736490264535, -0.005218582693487 },
{-0.001807302702218, 0.009130494669080, -0.033325243741274, 0.109637774527073, 0.973753631114960, -0.074447125196457, 0.020508514717221, -0.004077596124262 },
{-0.001750442315824, 0.006728826556355, -0.024075405672193, 0.077085755765438, 0.984105646610260, -0.054737392812967, 0.014606527984142, -0.002745266072452 },
{-0.001903604716063, 0.004479591734707, -0.015253192745149, 0.046474494040012, 0.991047739982605, -0.032752435654402, 0.008048813790083, -0.001216900418513 },
{0.000000000000000, 0.002400347497314, -0.006922415923327, 0.017910413444042, 0.994530856609344, -0.008521087467670, 0.000859897001646, 0.000499262532685 }};
float srslte_resample_arb_polyfilt_35[SRSLTE_RESAMPLE_ARB_N_35][SRSLTE_RESAMPLE_ARB_M] __attribute__((aligned(256))) =
{{0.000002955485215, 0.000657994314549, -0.033395686652146, 0.188481383863832, 0.704261032406613, 0.171322660416961, -0.032053439082436, 0.000722236729272},
{0.000003596427925, 0.000568080243211, -0.034615802155152, 0.206204344739138, 0.702921418438421, 0.154765509342932, -0.030612377229395, 0.000764085430796},
{0.000005121937258, 0.000449039680445, -0.035689076986744, 0.224449928603191, 0.700248311996698, 0.138842912406449, -0.029094366813032, 0.000786624971348},
{0.000007718609465, 0.000297261794949, -0.036589488825594, 0.243172347408947, 0.696253915778072, 0.123583456372980, -0.027519775698206, 0.000792734165095},
{0.000011575047600, 0.000109005258838, -0.037289794881918, 0.262321777662990, 0.690956433427623, 0.109011322456059, -0.025907443019580, 0.000785077624893},
{0.000016882508098, -0.000119571475197, -0.037761641428480, 0.281844530653151, 0.684379949985066, 0.095146306185631, -0.024274662580170, 0.000766100891437},
{0.000023834849457, -0.000392374989948, -0.037975689603840, 0.301683254255907, 0.676554274013489, 0.082003866618022, -0.022637179782782, 0.000738028846774},
{0.000032627688404, -0.000713336731203, -0.037901757319987, 0.321777165554580, 0.667514742706306, 0.069595203590358, -0.021009201268519, 0.000702867092175},
{0.000043456678971, -0.001086367817537, -0.037508976943232, 0.342062313218325, 0.657301991568526, 0.057927361522269, -0.019403416364306, 0.000662405963124},
{0.000056514841640, -0.001515308860252, -0.036765968249551, 0.362471868314761, 0.645961690553484, 0.047003358086968, -0.017831029382043, 0.000618226851332},
{0.000071988882997, -0.002003874882511, -0.035641025985104, 0.382936441958648, 0.633544248803284, 0.036822335913581, -0.016301801765629, 0.000571710504985},
{0.000090054461223, -0.002555595491550, -0.034102321191048, 0.403384427938144, 0.620104490387788, 0.027379735343965, -0.014824103048525, 0.000524046983526},
{0.000110870369116, -0.003173750525766, -0.032118115280935, 0.423742368211529, 0.605701303660781, 0.018667486151043, -0.013404969563367, 0.000476246951838},
{0.000134571624077, -0.003861301468941, -0.029656985690720, 0.443935338933583, 0.590397267050922, 0.010674216032341, -0.012050169836157, 0.000429154010367},
{0.000161261473605, -0.004620818996097, -0.026688061757620, 0.463887354454611, 0.574258254277514, 0.003385473622292, -0.010764275599988, 0.000383457772129},
{0.000191002345063, -0.005454407088752, -0.023181269326746, 0.483521786538780, 0.557353022125450, -0.003216036280022, -0.009550737376604, 0.000339707414324},
{0.000223805789820, -0.006363624230896, -0.019107582435436, 0.502761795874207, 0.539752784028766, -0.009150207594916, -0.008411963597610, 0.000298325451050},
{0.000259621494011, -0.007349402269867, -0.014439280286493, 0.521530772797177, 0.521530772797177, -0.014439280286493, -0.007349402269867, 0.000259621494011},
{0.000298325451050, -0.008411963597610, -0.009150207594916, 0.539752784028765, 0.502761795874207, -0.019107582435436, -0.006363624230896, 0.000223805789820},
{0.000339707414324, -0.009550737376604, -0.003216036280022, 0.557353022125450, 0.483521786538780, -0.023181269326746, -0.005454407088752, 0.000191002345063},
{0.000383457772129, -0.010764275599988, 0.003385473622292, 0.574258254277514, 0.463887354454611, -0.026688061757620, -0.004620818996097, 0.000161261473605},
{0.000429154010367, -0.012050169836157, 0.010674216032341, 0.590397267050922, 0.443935338933583, -0.029656985690720, -0.003861301468941, 0.000134571624077},
{0.000476246951838, -0.013404969563367, 0.018667486151043, 0.605701303660781, 0.423742368211529, -0.032118115280935, -0.003173750525766, 0.000110870369116},
{0.000524046983526, -0.014824103048525, 0.027379735343965, 0.620104490387787, 0.403384427938144, -0.034102321191048, -0.002555595491550, 0.000090054461223},
{0.000571710504985, -0.016301801765629, 0.036822335913581, 0.633544248803283, 0.382936441958648, -0.035641025985104, -0.002003874882511, 0.000071988882997},
{0.000618226851332, -0.017831029382043, 0.047003358086968, 0.645961690553484, 0.362471868314761, -0.036765968249551, -0.001515308860252, 0.000056514841640},
{0.000662405963124, -0.019403416364306, 0.057927361522269, 0.657301991568526, 0.342062313218325, -0.037508976943232, -0.001086367817537, 0.000043456678971},
{0.000702867092175, -0.021009201268519, 0.069595203590358, 0.667514742706306, 0.321777165554580, -0.037901757319987, -0.000713336731203, 0.000032627688404},
{0.000738028846774, -0.022637179782782, 0.082003866618022, 0.676554274013489, 0.301683254255907, -0.037975689603840, -0.000392374989948, 0.000023834849457},
{0.000766100891437, -0.024274662580170, 0.095146306185631, 0.684379949985066, 0.281844530653151, -0.037761641428480, -0.000119571475197, 0.000016882508098},
{0.000785077624893, -0.025907443019580, 0.109011322456059, 0.690956433427623, 0.262321777662990, -0.037289794881918, 0.000109005258838, 0.000011575047600},
{0.000792734165095, -0.027519775698206, 0.123583456372980, 0.696253915778072, 0.243172347408947, -0.036589488825594, 0.000297261794949, 0.000007718609465},
{0.000786624971348, -0.029094366813032, 0.138842912406449, 0.700248311996698, 0.224449928603191, -0.035689076986744, 0.000449039680445, 0.000005121937258},
{0.000764085430796, -0.030612377229395, 0.154765509342932, 0.702921418438421, 0.206204344739138, -0.034615802155152, 0.000568080243211, 0.000003596427925},
{0.000722236729272, -0.032053439082436, 0.171322660416961, 0.704261032406613, 0.188481383863832, -0.033395686652146, 0.000657994314549 , 0.000002955485215}};
static inline cf_t srslte_resample_arb_dot_prod(cf_t* x, float *y, int len){
cf_t res1 = srslte_vec_dot_prod_cfc(x,y,len);
return res1;
}
// Right-shift our window of samples
void srslte_resample_arb_push(srslte_resample_arb_t *q, cf_t x)
{
void srslte_resample_arb_push(srslte_resample_arb_t *q, cf_t x){
memmove(&q->reg[1], &q->reg[0], (SRSLTE_RESAMPLE_ARB_M-1)*sizeof(cf_t));
q->reg[0] = x;
}
// Initialize our struct
void srslte_resample_arb_init(srslte_resample_arb_t *q, float rate){
void srslte_resample_arb_init(srslte_resample_arb_t *q, float rate, bool interpolate){
memset(q->reg, 0, SRSLTE_RESAMPLE_ARB_M*sizeof(cf_t));
q->acc = 0.0;
q->rate = rate;
q->interpolate = interpolate;
q->step = (1/rate)*SRSLTE_RESAMPLE_ARB_N;
}
@ -94,19 +134,48 @@ int srslte_resample_arb_compute(srslte_resample_arb_t *q, cf_t *input, cf_t *out
int cnt = 0;
int n_out = 0;
int idx = 0;
cf_t res1,res2;
cf_t *filter_input;
float frac = 0;
memset(q->reg, 0, SRSLTE_RESAMPLE_ARB_M*sizeof(cf_t));
while (cnt < n_in) {
if(cnt<SRSLTE_RESAMPLE_ARB_M){
memcpy(&q->reg[SRSLTE_RESAMPLE_ARB_M - cnt], input, (cnt)*sizeof(cf_t));
filter_input = q->reg;
} else{
filter_input = &input[cnt-SRSLTE_RESAMPLE_ARB_M];
}
res1 = srslte_resample_arb_dot_prod(filter_input, srslte_resample_arb_polyfilt[idx], SRSLTE_RESAMPLE_ARB_M);
if(q->interpolate){
res2 = srslte_resample_arb_dot_prod(filter_input, srslte_resample_arb_polyfilt[(idx%SRSLTE_RESAMPLE_ARB_N)+1], SRSLTE_RESAMPLE_ARB_M);
}
while(cnt < n_in)
{
*output = srslte_resample_arb_dot_prod(q->reg, srslte_resample_arb_polyfilt[idx], SRSLTE_RESAMPLE_ARB_M);
if(idx == SRSLTE_RESAMPLE_ARB_N){
*output = res1;
}else {
*output = (q->interpolate)?(res1 + (res2-res1)*frac):res1;
}
output++;
n_out++;
q->acc += q->step;
idx = (int)roundf(q->acc);
idx = (int)(q->acc);
while(idx >= SRSLTE_RESAMPLE_ARB_N){
q->acc -= SRSLTE_RESAMPLE_ARB_N;
idx -= SRSLTE_RESAMPLE_ARB_N;
if(cnt < n_in)
srslte_resample_arb_push(q, input[cnt++]);
if(cnt < n_in){
cnt++;
}
}
if(q->interpolate){
frac = q->acc - idx;
if(frac < 0)
frac = frac*(-1);
}
}
return n_out;

View File

@ -35,9 +35,9 @@
#include "srslte/phy/resampling/resample_arb.h"
#define ITERATIONS 10000
int main(int argc, char **argv) {
int N=10000000;
int N=9000;
float rate = 24.0/25.0;
cf_t *in = malloc(N*sizeof(cf_t));
cf_t *out = malloc(N*sizeof(cf_t));
@ -46,12 +46,15 @@ int main(int argc, char **argv) {
in[i] = sin(i*2*M_PI/100);
srslte_resample_arb_t r;
srslte_resample_arb_init(&r, rate);
srslte_resample_arb_init(&r, rate, 0);
clock_t start = clock(), diff;
//int n_out = srslte_resample_arb_compute(&r, in, out, N);
for(int xx = 0; xx<ITERATIONS;xx++){
srslte_resample_arb_compute(&r, in, out, N);
}
diff = clock() - start;
diff = diff/ITERATIONS;
int msec = diff * 1000 / CLOCKS_PER_SEC;
float thru = (CLOCKS_PER_SEC/(float)diff)*(N/1e6);
printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec%1000);

View File

@ -35,12 +35,14 @@
#include "srslte/phy/resampling/resample_arb.h"
int main(int argc, char **argv) {
int N = 100; // Number of sinwave samples
int delay = 5; // Delay of our resampling filter
float down = 25.0; // Downsampling rate
for(int up=1;up<down;up++)
{
float rate = up/down;
@ -62,7 +64,7 @@ int main(int argc, char **argv) {
// Resample
srslte_resample_arb_t r;
srslte_resample_arb_init(&r, rate);
srslte_resample_arb_init(&r, rate, 0);
int n_out = srslte_resample_arb_compute(&r, in, out, N);
// Check interp values
@ -74,12 +76,11 @@ int main(int argc, char **argv) {
float diff = fabs(creal(in[pre])-creal(in[post]));
float diff2 = fabs(creal(out[i])-creal(in[round]));
if(diff2 > diff && pre != post){
printf("Interpolation failed at index %f", idx);
printf("Interpolation failed at index %f\n", idx);
exit(-1);
}
}
free(in);
free(out);
}

View File

@ -41,7 +41,7 @@ int rf_get_available_devices(char **devnames, int max_strlen) {
double srslte_rf_set_rx_gain_th(srslte_rf_t *rf, double gain)
{
if (gain > rf->new_rx_gain + 0.5 || gain < rf->new_rx_gain - 0.5) {
if (gain > rf->new_rx_gain + 2 || gain < rf->new_rx_gain - 2) {
pthread_mutex_lock(&rf->mutex);
rf->new_rx_gain = gain;
pthread_cond_signal(&rf->cond);
@ -69,6 +69,7 @@ static void* thread_gain_fcn(void *h) {
srslte_rf_set_rx_gain(h, rf->cur_rx_gain);
}
if (rf->tx_gain_same_rx) {
printf("setting also tx\n");
srslte_rf_set_tx_gain(h, rf->cur_rx_gain+rf->tx_rx_gain_offset);
}
pthread_mutex_unlock(&rf->mutex);

View File

@ -38,6 +38,7 @@
#include <SoapySDR/Formats.h>
typedef struct {
char *devname;
SoapySDRKwargs args;
SoapySDRDevice *device;
SoapySDRRange *ranges;
@ -51,7 +52,6 @@ typedef struct {
cf_t zero_mem[64*1024];
int soapy_error(void *h)
{
return 0;
@ -90,7 +90,8 @@ void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t ne
char* rf_soapy_devname(void* h)
{
return "soapy";
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
return handler->devname;
}
@ -196,11 +197,15 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
printf("No Soapy devices found.\n");
return SRSLTE_ERROR;
}
char* devname;
for (size_t i = 0; i < length; i++) {
printf("Soapy has Found device #%d: ", (int)i);
for (size_t j = 0; j < soapy_args[i].size; j++) {
printf("%s=%s, ", soapy_args[i].keys[j], soapy_args[i].vals[j]);
if(!strcmp(soapy_args[i].keys[j],"name") && !strcmp(soapy_args[i].vals[j], "LimeSDR-USB")){
devname = DEVNAME_LIME;
}
}
printf("\n");
}
@ -218,7 +223,7 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
handler->device = sdr;
handler->tx_stream_active = false;
handler->rx_stream_active = false;
handler->devname = devname;
if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_RX) > 0){
printf("setting up RX stream\n");
if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) {
@ -234,6 +239,14 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
return SRSLTE_ERROR;
}
}
size_t sensor_length;
char** sensors;
sensors = SoapySDRDevice_listSensors(handler->device, &sensor_length);
for(int i = 0; i < sensor_length;i++)
{
printf("available sensors are : \n");
puts(sensors[i]);
}
return SRSLTE_SUCCESS;
}
@ -267,7 +280,7 @@ int rf_soapy_close(void *h)
void rf_soapy_set_master_clock_rate(void *h, double rate)
{
// Allow the soapy to automatically set the appropriate clock rate
// TODO: implement this function
}
@ -285,7 +298,6 @@ double rf_soapy_set_rx_srate(void *h, double rate)
printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0);
}
@ -296,7 +308,6 @@ double rf_soapy_set_tx_srate(void *h, double rate)
printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0);
}

View File

@ -28,7 +28,7 @@
#include <stdint.h>
#include "srslte/config.h"
#include "srslte/phy/rf/rf.h"
#define DEVNAME_LIME "lime"
SRSLTE_API int rf_soapy_open(char *args,
void **handler);

View File

@ -293,6 +293,13 @@ int rf_uhd_open(char *args, void **h)
return rf_uhd_open_multi(args, h, 1);
}
#define REMOVE_SUBSTRING_WITHCOMAS(S, TOREMOVE) \
remove_substring(S, TOREMOVE ",");\
remove_substring(S, TOREMOVE ", ");\
remove_substring(S, "," TOREMOVE);\
remove_substring(S, ", " TOREMOVE);\
remove_substring(S, TOREMOVE)
static void remove_substring(char *s,const char *toremove)
{
while((s=strstr(s,toremove))) {
@ -300,6 +307,17 @@ static void remove_substring(char *s,const char *toremove)
}
}
static void copy_subdev_string(char *dst, char *src) {
int n = 0;
size_t len = strlen(src);
/* Copy until end of string or comma */
while (n < len && src[n] != '\0' && src[n] != ',') {
dst[n] = src[n];
n++;
}
dst[n] = '\0';
}
int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
{
if (h) {
@ -338,11 +356,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
// Check external clock argument
enum {DEFAULT, EXTERNAL, GPSDO} clock_src;
if (strstr(args, "clock=external")) {
remove_substring(args, "clock=external");
REMOVE_SUBSTRING_WITHCOMAS(args, "clock=external");
clock_src = EXTERNAL;
} else if (strstr(args, "clock=gpsdo")) {
printf("Using GPSDO clock\n");
remove_substring(args, "clock=gpsdo");
REMOVE_SUBSTRING_WITHCOMAS(args, "clock=gpsdo");
clock_src = GPSDO;
} else {
clock_src = DEFAULT;
@ -351,14 +369,42 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
// Set over the wire format
char *otw_format = "sc16";
if (strstr(args, "otw_format=sc12")) {
REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc12");
otw_format = "sc12";
} else if (strstr(args, "otw_format=sc16")) {
REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc16");
/* Do nothing */
} else if (strstr(args, "otw_format=")) {
fprintf(stderr, "Wrong over the wire format. Valid formats: sc12, sc16\n");
return -1;
}
// Set transmitter subdevice spec string
const char tx_subdev_arg[] = "tx_subdev_spec=";
char tx_subdev_str[64] = {0};
char *tx_subdev_ptr = strstr(args, tx_subdev_arg);
if (tx_subdev_ptr) {
copy_subdev_string(tx_subdev_str, tx_subdev_ptr + strlen(tx_subdev_arg));
}
// Set receiver subdevice spec string
const char rx_subdev_arg[] = "rx_subdev_spec=";
char rx_subdev_str[64] = {0};
char *rx_subdev_ptr = strstr(args, rx_subdev_arg);
if (rx_subdev_ptr) {
copy_subdev_string(rx_subdev_str, rx_subdev_ptr + strlen(rx_subdev_arg));
}
if (tx_subdev_ptr) {
remove_substring(args, tx_subdev_arg);
remove_substring(args, tx_subdev_str);
}
if (rx_subdev_ptr) {
remove_substring(args, rx_subdev_arg);
remove_substring(args, rx_subdev_str);
}
/* If device type or name not given in args, choose a B200 */
if (args[0]=='\0') {
if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) {
@ -398,7 +444,29 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
fprintf(stderr, "Error opening UHD: code %d\n", error);
return -1;
}
/* Set transmitter subdev spec if specified */
if (strlen(tx_subdev_str)) {
uhd_subdev_spec_handle subdev_spec_handle = {0};
printf("Setting tx_subdev_spec to '%s'\n", tx_subdev_str);
uhd_subdev_spec_make(&subdev_spec_handle, tx_subdev_str);
uhd_usrp_set_tx_subdev_spec(handler->usrp, subdev_spec_handle, 0);
uhd_subdev_spec_free(&subdev_spec_handle);
}
/* Set receiver subdev spec if specified */
if (strlen(rx_subdev_str)) {
uhd_subdev_spec_handle subdev_spec_handle = {0};
printf("Setting rx_subdev_spec to '%s'\n", rx_subdev_str);
uhd_subdev_spec_make(&subdev_spec_handle, rx_subdev_str);
uhd_usrp_set_rx_subdev_spec(handler->usrp, subdev_spec_handle, 0);
uhd_subdev_spec_free(&subdev_spec_handle);
}
if (!handler->devname) {
char dev_str[1024];
uhd_usrp_get_mboard_name(handler->usrp, 0, dev_str, 1024);

View File

@ -586,19 +586,21 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos);
}
}
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
ret = SRSLTE_SYNC_FOUND;
} else {
ret = SRSLTE_SYNC_FOUND_NOSPACE;
if (q->enable_cfo_corr) {
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
ret = SRSLTE_SYNC_FOUND;
} else {
ret = SRSLTE_SYNC_FOUND_NOSPACE;
}
}
} else {
ret = SRSLTE_SYNC_NOFOUND;

View File

@ -308,7 +308,38 @@ void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q,
srslte_ofdm_set_non_mbsfn_region(&q->fft_mbsfn, non_mbsfn_region_length);
}
void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q, float rho_a, float rho_b) {
if (q) {
srslte_pdsch_set_power_allocation(&q->pdsch, rho_a);
q->rho_b = rho_b;
uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb;
/* Apply rho_b if required according to 3GPP 36.213 Table 5.2-2 */
if (rho_b != 0.0f && rho_b != 1.0f) {
float scaling = 1.0f / rho_b;
for (uint32_t i = 0; i < q->nof_rx_antennas; i++) {
for (uint32_t j = 0; j < 2; j++) {
cf_t *ptr;
ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 0);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
if (q->cell.cp == SRSLTE_CP_NORM) {
ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 4);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
} else {
ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 3);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
if (q->cell.nof_ports == 4) {
ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 1);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
}
}
}
}
}
void srslte_ue_dl_reset(srslte_ue_dl_t *q) {
for(int i = 0; i < SRSLTE_MAX_CODEWORDS; i++){

View File

@ -47,6 +47,10 @@
#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0
#define DEFAULT_SFO_EMA_COEFF 0.1
//#define DO_CFO_IN_SYNC
cf_t dummy_buffer0[15*2048/2];
cf_t dummy_buffer1[15*2048/2];
@ -118,6 +122,8 @@ int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(voi
q->do_agc = n==0?true:false;
if (q->do_agc) {
srslte_agc_set_gain(&q->agc, init_gain_value);
srslte_agc_set_target(&q->agc, 0.3);
srslte_agc_set_bandwidth(&q->agc, 0.8);
}
return n;
}
@ -182,6 +188,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD;
q->sfo_ema = DEFAULT_SFO_EMA_COEFF;
q->mean_cfo_isunset = true;
q->mean_cfo = 0;
q->cfo_ema_alpha = 0.4;
q->max_prb = max_prb;
if (search_cell) {
@ -218,6 +227,11 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
}
}
#ifndef DO_CFO_IN_SYNC
// Disable CFO correction in sync object and do it here every subframe
srslte_sync_set_cfo_enable(&q->strack, false);
#endif
ret = SRSLTE_SUCCESS;
}
@ -362,6 +376,7 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) {
void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) {
srslte_sync_set_cfo_ema_alpha(&q->sfind, ema);
srslte_sync_set_cfo_ema_alpha(&q->strack, ema);
q->cfo_ema_alpha = ema;
}
srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) {
@ -377,7 +392,11 @@ void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable) {
}
float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) {
#ifdef DO_CFO_IN_SYNC
return 15000 * srslte_sync_get_cfo(&q->strack);
#else
return 15000 * q->mean_cfo;
#endif
}
void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
@ -662,6 +681,23 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10;
#ifndef DO_CFO_IN_SYNC
/* We found that CP-based correction performs better in low SNR than PSS-based.
*
* Estimate, average and correct here instead of inside sync object
*/
q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0);
if (q->mean_cfo_isunset) {
q->mean_cfo = q->cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha);
}
srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size);
#endif
/* Every SF idx 0 and 5, find peak around known position q->peak_idx */
if (q->sf_idx == 0 || q->sf_idx == 5) {

View File

@ -453,7 +453,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
if (srslte_pusch_encode(&q->pusch, &q->pusch_cfg, softbuffer, data, uci_data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
return SRSLTE_ERROR;
}
if (q->signals_pregenerated) {

View File

@ -24,7 +24,14 @@
*
*/
#include <pthread.h>
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include "srslte/phy/utils/debug.h"
#include "srslte/version.h"
int srslte_verbose = 0;
@ -37,3 +44,57 @@ void get_time_interval(struct timeval * tdata) {
tdata[0].tv_usec += 1000000;
}
}
const static char crash_file_name[] = "./srsLTE.backtrace.crash";
static int bt_argc;
static char **bt_argv;
static void crash_handler(int sig) {
void *array[128];
int size;
/* Get all stack traces */
size = backtrace(array, 128);
FILE *f = fopen(crash_file_name, "a");
if (!f) {
printf("srsLTE crashed... we could not save backtrace in '%s'...\n", crash_file_name);
} else {
char **symbols = backtrace_symbols(array, size);
time_t lnTime;
struct tm *stTime;
char strdate[32];
time(&lnTime);
stTime = localtime(&lnTime);
strftime(strdate, 32, "%d/%m/%Y %H:%M:%S", stTime);
fprintf(f, "--- command='");
for (int i = 0; i < bt_argc; i++) {
fprintf(f, "%s%s", (i == 0) ? "" : " ", bt_argv[i]);
}
fprintf(f, "' version=%s signal=%d date='%s' ---\n", SRSLTE_VERSION_STRING, sig, strdate);
for (int i = 0; i < size; i++) {
fprintf(f, "\t%s\n", symbols[i]);
}
fprintf(f, "\n");
printf("srsLTE crashed... backtrace saved in '%s'...\n", crash_file_name);
fclose(f);
}
printf("--- exiting ---\n");
exit(1);
}
void srslte_debug_handle_crash(int argc, char **argv) {
bt_argc = argc;
bt_argv = argv;
signal(SIGSEGV, crash_handler);
signal(SIGABRT, crash_handler);
signal(SIGILL, crash_handler);
signal(SIGFPE, crash_handler);
}

View File

@ -502,6 +502,7 @@ TEST(srslte_vec_abs_cf,
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
x[0] = 0.0f;
TEST_CALL(srslte_vec_abs_cf(x, z, block_size))

View File

@ -199,7 +199,6 @@ void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, int len) {
}
}
/* Modified from volk_32f_s32f_convert_16i_a_simd2. Removed clipping */
void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, int len) {
int i = 0;

View File

@ -59,6 +59,7 @@ bool radio::init(char *args, char *devname)
} else if (strstr(srslte_rf_name(&rf_device), "bladerf")) {
burst_preamble_sec = blade_default_burst_preamble_sec;
} else {
burst_preamble_sec = 0;
printf("\nWarning burst preamble is not calibrated for device %s. Set a value manually\n\n", srslte_rf_name(&rf_device));
}
@ -329,11 +330,10 @@ void radio::set_tx_srate(double srate)
}
burst_preamble_time_rounded = (double) burst_preamble_samples/cur_tx_srate;
int nsamples=0;
/* Set time advance for each known device if in auto mode */
if (tx_adv_auto) {
/* This values have been calibrated using the prach_test_usrp tool in srsLTE */
if (!strcmp(srslte_rf_name(&rf_device), "uhd_b200")) {
@ -355,7 +355,48 @@ void radio::set_tx_srate(double srate)
/* Interpolate from known values */
printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate);
nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec);
}
}
}else if(!strcmp(srslte_rf_name(&rf_device), "uhd_usrp2")) {
double srate_khz = round(cur_tx_srate/1e3);
if (srate_khz == 1.92e3) {
nsamples = 14;// estimated
} else if (srate_khz == 3.84e3) {
nsamples = 32;
} else if (srate_khz == 5.76e3) {
nsamples = 43;
} else if (srate_khz == 11.52e3) {
nsamples = 54;
} else if (srate_khz == 15.36e3) {
nsamples = 65;// to calc
} else if (srate_khz == 23.04e3) {
nsamples = 80; // to calc
} else {
/* Interpolate from known values */
printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate);
nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec);
}
} else if(!strcmp(srslte_rf_name(&rf_device), "lime")) {
double srate_khz = round(cur_tx_srate/1e3);
if (srate_khz == 1.92e3) {
nsamples = 70;// estimated
} else if (srate_khz == 3.84e3) {
nsamples = 76;//estimated
} else if (srate_khz == 5.76e3) {
nsamples = 76;
} else if (srate_khz == 11.52e3) {
nsamples = 76;
} else if (srate_khz == 15.36e3) {
nsamples = 73;
} else if (srate_khz == 23.04e3) {
nsamples = 87;
} else {
/* Interpolate from known values */
printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate);
nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec);
}
} else if (!strcmp(srslte_rf_name(&rf_device), "uhd_x300")) {
// In X300 TX/RX offset is independent of sampling rate

View File

@ -201,8 +201,14 @@ uint32_t rlc_am::get_total_buffer_state()
rlc_amd_retx_t retx = retx_queue.front();
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
if(tx_window.end() != tx_window.find(retx.sn)) {
n_bytes += required_buffer_size(retx);
int req_bytes = required_buffer_size(retx);
if (req_bytes < 0) {
log->error("In get_total_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
retx_queue.pop_front();
} else {
n_bytes += req_bytes;
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
}
}
}
@ -250,7 +256,13 @@ uint32_t rlc_am::get_buffer_state()
rlc_amd_retx_t retx = retx_queue.front();
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
if(tx_window.end() != tx_window.find(retx.sn)) {
n_bytes = required_buffer_size(retx);
int req_bytes = required_buffer_size(retx);
if (req_bytes < 0) {
log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
retx_queue.pop_front();
goto unlock_and_return;
}
n_bytes = (uint32_t) req_bytes;
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
goto unlock_and_return;
}
@ -296,8 +308,9 @@ int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes)
}
// RETX if required
if(retx_queue.size() > 0) {
int ret = build_retx_pdu(payload, nof_bytes);
pthread_mutex_unlock(&mutex);
return build_retx_pdu(payload, nof_bytes);
return ret;
}
// Build a PDU from SDUs
@ -438,16 +451,33 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes)
int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
{
// Check there is at least 1 element before calling front()
if (retx_queue.empty()) {
log->error("In build_retx_pdu(): retx_queue is empty\n");
return -1;
}
rlc_amd_retx_t retx = retx_queue.front();
// Sanity check - drop any retx SNs not present in tx_window
while(tx_window.end() == tx_window.find(retx.sn)) {
retx_queue.pop_front();
retx = retx_queue.front();
if (!retx_queue.empty()) {
retx = retx_queue.front();
} else {
log->error("In build_retx_pdu(): retx_queue is empty during sanity check\n");
return -1;
}
}
// Is resegmentation needed?
if(retx.is_segment || required_buffer_size(retx) > (int)nof_bytes) {
int req_size = required_buffer_size(retx);
if (req_size < 0) {
log->error("In build_retx_pdu(): Removing retx.sn=%d from queue\n", retx.sn);
retx_queue.pop_front();
return -1;
}
if(retx.is_segment || req_size > (int)nof_bytes) {
log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str());
return build_segment(payload, nof_bytes, retx);
}
@ -481,6 +511,10 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx)
{
if (!tx_window[retx.sn].buf) {
log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn);
return 0;
}
if(!retx.is_segment){
retx.so_start = 0;
retx.so_end = tx_window[retx.sn].buf->N_bytes;
@ -1147,7 +1181,17 @@ bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pd
int rlc_am::required_buffer_size(rlc_amd_retx_t retx)
{
if(!retx.is_segment){
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
if (tx_window.count(retx.sn)) {
if (tx_window[retx.sn].buf) {
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
} else {
log->warning("retx.sn=%d has null ptr in required_buffer_size()\n", retx.sn);
return -1;
}
} else {
log->warning("retx.sn=%d does not exist in required_buffer_size()\n", retx.sn);
return -1;
}
}
// Construct new header

View File

@ -95,7 +95,7 @@ private:
srslte_enb_dl_t enb_dl;
srslte_enb_ul_t enb_ul;
srslte_timestamp_t tx_time;
srslte_timestamp_t tx_time;
// Class to store user information
class ue {
@ -112,6 +112,11 @@ private:
void metrics_read(phy_metrics_t *metrics);
void metrics_dl(uint32_t mcs);
void metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t turbo_iters);
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
private:
phy_metrics_t metrics;
};

View File

@ -709,7 +709,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
/* Indicate PHICH acknowledgment if needed */
if (h->has_pending_ack()) {
sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK;
sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK;
sched_result->phich[nof_phich_elems].rnti = rnti;
nof_phich_elems++;
}
@ -767,7 +767,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
{
ul_harq_proc::ul_alloc_t alloc = h->get_alloc();
bool is_newtx = h->is_empty();
bool needs_pdcch = !h->is_adaptive_retx() && !is_rar;
bool needs_pdcch = h->is_adaptive_retx() && !is_rar;
// Set number of retx
if (is_newtx) {

View File

@ -198,13 +198,13 @@ ul_harq_proc::ul_alloc_t ul_harq_proc::get_alloc()
void ul_harq_proc::set_alloc(ul_harq_proc::ul_alloc_t alloc)
{
is_adaptive = false;
is_adaptive = true;
memcpy(&allocation, &alloc, sizeof(ul_alloc_t));
}
void ul_harq_proc::same_alloc()
{
is_adaptive = true;
is_adaptive = false;
}
bool ul_harq_proc::is_adaptive_retx()
@ -243,8 +243,7 @@ void ul_harq_proc::reset_pending_data()
}
}
uint32_t ul_harq_proc::get_pending_data()
uint32_t ul_harq_proc::get_pending_data()
{
return pending_data;
}

View File

@ -25,11 +25,6 @@
*/
#include <string.h>
#include <boost/concept_check.hpp>
#include <srslte/interfaces/sched_interface.h>
#include <srslte/phy/phch/pucch.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/srslte.h"
#include "srslte/common/pdu.h"
@ -395,32 +390,32 @@ int sched_ue::generate_format1(dl_harq_proc *h,
mcs = fixed_mcs_dl;
}
h->new_tx(tti, mcs, tbs, data->dci_location.ncce);
h->new_tx(tti, mcs, tbs, data->dci_location.ncce);
// Allocate MAC ConRes CE
if (need_conres_ce) {
data->pdu[0].lcid = srslte::sch_subh::CON_RES_ID;
data->nof_pdu_elems++;
Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti);
}
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems++;
}
} while(rem_tbs > 0 && x > 0);
Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else {
h->new_retx(tti, &mcs, &tbs);
Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs);
}
// Allocate MAC ConRes CE
if (need_conres_ce) {
data->pdu[0].lcid = srslte::sch_subh::CON_RES_ID;
data->nof_pdu_elems++;
Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti);
}
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems++;
}
} while(rem_tbs > 0 && x > 0);
data->rnti = rnti;
data->rnti = rnti;
if (tbs > 0) {
dci->harq_process = h->get_id();
@ -449,7 +444,8 @@ int sched_ue::generate_format0(ul_harq_proc *h,
int tbs = 0;
ul_harq_proc::ul_alloc_t allocation = h->get_alloc();
bool is_newtx = true;
if (h->get_rar_mcs(&mcs)) {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
h->new_tx(tti, mcs, tbs);
@ -468,7 +464,8 @@ int sched_ue::generate_format0(ul_harq_proc *h,
h->new_tx(tti, mcs, tbs);
} else {
} else {
is_newtx = false;
h->new_retx(tti, &mcs, NULL);
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
}
@ -479,9 +476,13 @@ int sched_ue::generate_format0(ul_harq_proc *h,
if (tbs > 0) {
dci->type2_alloc.L_crb = allocation.L;
dci->type2_alloc.RB_start = allocation.RB_start;
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx());
dci->ndi = h->get_ndi();
dci->rv_idx = sched::get_rvidx(h->nof_retx());
if (!is_newtx && h->is_adaptive_retx()) {
dci->mcs_idx = 28+dci->rv_idx;
} else {
dci->mcs_idx = mcs;
}
dci->ndi = h->get_ndi();
dci->cqi_request = cqi_request;
dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED;
dci->tpc_pusch = next_tpc_pusch;

View File

@ -350,6 +350,8 @@ int main(int argc, char *argv[])
metrics_stdout metrics;
enb *enb = enb::get_instance();
srslte_debug_handle_crash(argc, argv);
cout << "--- Software Radio Systems LTE eNodeB ---" << endl << endl;
parse_args(&args, argc, argv);

View File

@ -412,6 +412,22 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
srslte_ra_ul_grant_t phy_grant;
int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) {
// Handle Format0 adaptive retx
// Use last TBS for this TB in case of mcs>28
if (phy_grant.mcs.idx > 28) {
phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)];
Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS));
}
ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs;
if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) {
phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)];
phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod);
}
ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod;
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
phy_grant.mcs.mod = SRSLTE_MOD_16QAM;
}

View File

@ -44,39 +44,35 @@
namespace srsue {
template <std::size_t N, typename Tgrant, typename Taction, typename Tphygrant>
class ul_harq_entity
{
class ul_harq_entity {
public:
static uint32_t pidof(uint32_t tti)
{
return (uint32_t) tti%N;
static uint32_t pidof(uint32_t tti) {
return (uint32_t) tti % N;
}
ul_harq_entity() : proc(N)
{
ul_harq_entity() : proc(N) {
contention_timer = NULL;
pcap = NULL;
mux_unit = NULL;
log_h = NULL;
params = NULL;
rntis = NULL;
average_retx = 0;
nof_pkts = 0;
pcap = NULL;
mux_unit = NULL;
log_h = NULL;
params = NULL;
rntis = NULL;
average_retx = 0;
nof_pkts = 0;
}
bool init(srslte::log *log_h_,
bool init(srslte::log *log_h_,
mac_interface_rrc_common::ue_rnti_t *rntis_,
mac_interface_rrc_common::ul_harq_params_t *params_,
srslte::timers::timer* contention_timer_,
mux *mux_unit_)
{
log_h = log_h_;
mux_unit = mux_unit_;
params = params_;
rntis = rntis_;
srslte::timers::timer *contention_timer_,
mux *mux_unit_) {
log_h = log_h_;
mux_unit = mux_unit_;
params = params_;
rntis = rntis_;
contention_timer = contention_timer_;
for (uint32_t i=0;i<N;i++) {
for (uint32_t i = 0; i < N; i++) {
if (!proc[i].init(i, this)) {
return false;
}
@ -84,29 +80,29 @@ public:
return true;
}
void reset()
{
for (uint32_t i=0;i<N;i++) {
void reset() {
for (uint32_t i = 0; i < N; i++) {
proc[i].reset();
}
ul_sps_assig.clear();
}
void reset_ndi()
{
for (uint32_t i=0;i<N;i++) {
void reset_ndi() {
for (uint32_t i = 0; i < N; i++) {
proc[i].reset_ndi();
}
}
void start_pcap(srslte::mac_pcap* pcap_)
{
void start_pcap(srslte::mac_pcap *pcap_) {
pcap = pcap_;
}
/***************** PHY->MAC interface for UL processes **************************/
void new_grant_ul(Tgrant grant, Taction *action)
void new_grant_ul(Tgrant grant, Taction *action) {
new_grant_ul_ack(grant, NULL, action);
}
void new_grant_ul_ack(Tgrant grant, bool *ack, Taction *action)
{
if (grant.rnti_type == SRSLTE_RNTI_USER ||
grant.rnti_type == SRSLTE_RNTI_TEMP ||
@ -115,27 +111,20 @@ public:
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) {
grant.ndi[0] = true;
}
run_tti(grant.tti, &grant, action);
run_tti(grant.tti, &grant, ack, action);
} else if (grant.rnti_type == SRSLTE_RNTI_SPS) {
if (grant.ndi[0]) {
grant.ndi[0] = proc[pidof(grant.tti)].get_ndi();
run_tti(grant.tti, &grant, action);
run_tti(grant.tti, &grant, ack, action);
} else {
Info("Not implemented\n");
}
}
}
void new_grant_ul_ack(Tgrant grant, bool ack, Taction *action)
{
set_ack(grant.tti, ack, action);
new_grant_ul(grant, action);
}
void harq_recv(uint32_t tti, bool ack, Taction *action)
{
set_ack(tti, ack, action);
run_tti(tti, NULL, action);
run_tti(tti, NULL, &ack, action);
}
int get_current_tbs(uint32_t tti)
@ -206,10 +195,19 @@ private:
bzero(&cur_grant, sizeof(Tgrant));
}
void reset_ndi() { ndi = false; }
void run_tti(uint32_t tti_tx, Tgrant *grant, Taction* action)
void reset_ndi() { cur_grant.ndi[0] = false; }
void run_tti(uint32_t tti_tx, Tgrant *grant, bool *ack, Taction* action)
{
if (ack) {
if (grant) {
if (grant->ndi[0] == get_ndi()) {
*ack = false;
}
}
set_harq_feedback(*ack);
}
uint32_t max_retx;
if (is_msg3) {
max_retx = harq_entity->params->max_harq_msg3_tx;
@ -219,9 +217,9 @@ private:
// Receive and route HARQ feedbacks
if (grant) {
if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) ||
(grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) ||
grant->is_from_rar)
if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && ack) ||
(grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) ||
grant->is_from_rar)
{
// New transmission
@ -245,7 +243,7 @@ private:
Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n");
}
}
} else {
} else if (has_grant()) {
// Adaptive Re-TX
if (current_tx_nb >= max_retx) {
Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx);
@ -254,6 +252,8 @@ private:
} else {
generate_retx(tti_tx, grant, action);
}
} else {
Warning("UL %d: Received retransmission but no previous grant available for this PID.\n", pid);
}
} else if (has_grant()) {
// Non-Adaptive Re-Tx
@ -292,9 +292,8 @@ private:
}
bool has_grant() { return is_grant_configured; }
bool get_ndi() { return ndi; }
bool get_ndi() { return cur_grant.ndi[0]; }
bool is_sps() { return false; }
uint32_t last_tx_tti() { return tti_last_tx; }
uint32_t get_nof_retx() { return current_tx_nb; }
int get_current_tbs() { return cur_grant.n_bytes[0]*8; }
@ -305,7 +304,6 @@ private:
uint32_t current_tx_nb;
uint32_t current_irv;
bool harq_feedback;
bool ndi;
srslte::log *log_h;
ul_harq_entity *harq_entity;
bool is_grant_configured;
@ -396,24 +394,12 @@ private:
// Implements Section 5.4.2.1
// Called with UL grant
void run_tti(uint32_t tti, Tgrant *grant, Taction* action)
void run_tti(uint32_t tti, Tgrant *grant, bool *ack, Taction* action)
{
uint32_t tti_tx = (tti+action->tti_offset)%10240;
proc[pidof(tti_tx)].run_tti(tti_tx, grant, action);
proc[pidof(tti_tx)].run_tti(tti_tx, grant, ack, action);
}
void set_ack(uint32_t tti, bool ack, Taction *action)
{
int tti_harq = (int) tti - action->tti_offset;
if (tti_harq < 0) {
tti_harq += 10240;
}
uint32_t pid_harq = pidof(tti_harq);
if (proc[pid_harq].has_grant() && (proc[pid_harq].last_tx_tti() <= (uint32_t)tti_harq)) {
proc[pid_harq].set_harq_feedback(ack);
}
}
ul_sps ul_sps_assig;
srslte::timers::timer *contention_timer;

View File

@ -69,6 +69,14 @@ namespace srsue {
bool pcell_meas_enabled;
uint32_t pcell_report_period;
// Save last TBS for mcs>28 cases
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
uint32_t last_dl_tti[2*HARQ_DELAY_MS];
int last_ul_tbs[2*HARQ_DELAY_MS];
uint32_t last_ul_tti[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
phch_common(uint32_t max_mutex = 3);
void init(phy_interface_rrc::phy_cfg_t *config,
phy_args_t *args,
@ -144,7 +152,7 @@ namespace srsue {
uint32_t n_dmrs;
} pending_ack_t;
pending_ack_t pending_ack[TTIMOD_SZ];
bool is_first_tx;
uint32_t nof_workers;

View File

@ -80,6 +80,7 @@ public:
const static int MUTEX_X_WORKER = 4;
double set_rx_gain(double gain);
int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
int scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);

View File

@ -151,11 +151,6 @@ private:
float cfo;
bool rar_cqi_request;
// Save last TBS for mcs>28 cases
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
// Metrics
dl_metrics_t dl_metrics;
ul_metrics_t ul_metrics;

View File

@ -38,6 +38,7 @@
#include "srslte/radio/radio_multi.h"
#include "phy/phy.h"
#include "upper/usim.h"
#include "upper/rrc.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/logger.h"
@ -104,12 +105,11 @@ typedef struct {
typedef struct {
std::string ip_netmask;
phy_args_t phy;
float metrics_period_secs;
bool pregenerate_signals;
std::string ue_cateogry;
bool metrics_csv_enable;
std::string metrics_csv_filename;
phy_args_t phy;
float metrics_period_secs;
bool pregenerate_signals;
bool metrics_csv_enable;
std::string metrics_csv_filename;
}expert_args_t;
typedef struct {
@ -120,6 +120,8 @@ typedef struct {
log_args_t log;
gui_args_t gui;
usim_args_t usim;
rrc_args_t rrc;
std::string ue_category_str;
expert_args_t expert;
}all_args_t;
@ -161,6 +163,10 @@ public:
srslte::log_filter rf_log;
rf_metrics_t rf_metrics;
srslte::LOG_LEVEL_ENUM level(std::string l);
std::string get_build_mode();
std::string get_build_info();
std::string get_build_string();
};
} // namespace srsue

View File

@ -57,6 +57,9 @@ static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL",
"DEREGISTERED INITIATED",
"TRACKING AREA UPDATE INITIATED"};
static const bool eia_caps[8] = {false, true, true, false, false, false, false, false};
static const bool eea_caps[8] = {true, false, false, false, false, false, false, false};
typedef enum {
PLMN_NOT_SELECTED = 0,
PLMN_SELECTED
@ -80,16 +83,12 @@ public:
// RRC interface
void notify_connection_setup();
void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
uint32_t get_ul_count();
bool is_attached();
bool is_attaching();
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);
bool get_k_asme(uint8_t *k_asme_, uint32_t n);
void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code);
void plmn_search_end();
@ -115,72 +114,73 @@ private:
std::vector<LIBLTE_RRC_PLMN_IDENTITY_STRUCT > known_plmns;
// Save short MAC
LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info;
// Identifiers
LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti;
bool is_guti_set;
bool have_guti;
// Security context
struct nas_sec_ctxt{
uint8_t ksi;
uint8_t k_asme[32];
uint32_t tx_count;
uint32_t rx_count;
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
};
bool have_ctxt;
nas_sec_ctxt ctxt;
uint32_t ip_addr;
uint8_t eps_bearer_id;
uint8_t transaction_id;
// NAS counters - incremented for each security-protected message recvd/sent
uint32_t count_ul;
uint32_t count_dl;
// Security
uint8_t ksi;
uint8_t k_nas_enc[32];
uint8_t k_nas_int[32];
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
void integrity_generate(uint8_t *key_128,
void integrity_generate(uint8_t integ_algo,
uint8_t *key_128,
uint32_t count,
uint8_t rb_id,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac);
void integrity_check();
void cipher_encrypt();
void cipher_decrypt();
bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps);
// Parsers
void parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu);
void parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu);
void parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu);
void parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu);
void parse_identity_request(uint32_t lcid, byte_buffer_t *pdu);
void parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu);
void parse_service_reject(uint32_t lcid, byte_buffer_t *pdu);
void parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu);
void parse_emm_information(uint32_t lcid, byte_buffer_t *pdu);
// Senders
void send_attach_request();
void send_identity_response();
void send_service_request();
void send_esm_information_response();
void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg);
void send_security_mode_reject(uint8_t cause);
// guti persistence file
bool read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti);
bool write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti);
// security context persistence file
bool read_ctxt_file(nas_sec_ctxt *ctxt);
bool write_ctxt_file(nas_sec_ctxt ctxt);
};
} // namespace srsue

View File

@ -40,6 +40,13 @@
#include <map>
#include <queue>
typedef struct {
uint32_t ue_category;
uint32_t feature_group;
uint8_t supported_bands[LIBLTE_RRC_BAND_N_ITEMS];
uint32_t nof_supported_bands;
}rrc_args_t;
using srslte::byte_buffer_t;
namespace srsue {
@ -74,7 +81,7 @@ public:
rrc_state_t get_state();
void set_ue_category(int category);
void set_args(rrc_args_t *args);
// Timeout callback interface
void timer_expired(uint32_t timeout_id);
@ -142,6 +149,9 @@ private:
uint8_t transaction_id;
bool drb_up;
rrc_args_t args;
bool first_stimsi_attempt;
bool reestablishment_in_progress;
bool pending_mob_reconf;
@ -174,10 +184,11 @@ private:
// RRC constants and timers
srslte::mac_interface_timers *mac_timers;
uint32_t sync_reset_cnt;
const static uint32_t SYNC_RESET_TIMEOUT = 10;
uint32_t n310_cnt, N310;
uint32_t n311_cnt, N311;
uint32_t t301, t310, t311, t304;
int ue_category;
typedef struct {
uint32_t earfcn;
@ -375,7 +386,6 @@ private:
void set_mac_default();
void set_rrc_default();
void set_bearers();
};
} // namespace srsue

View File

@ -1,4 +1,4 @@
/**
/**
*
* \section COPYRIGHT
*
@ -59,24 +59,30 @@ public:
void stop();
// NAS interface
void get_imsi_vec(uint8_t* imsi_, uint32_t n);
void get_imei_vec(uint8_t* imei_, uint32_t n);
int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id);
std::string get_imsi_str();
std::string get_imei_str();
bool get_imsi_vec(uint8_t* imsi_, uint32_t n);
bool get_imei_vec(uint8_t* imei_, uint32_t n);
bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id);
void generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res);
uint8_t *res,
uint8_t *k_asme);
void generate_nas_keys(uint8_t *k_nas_enc,
void generate_nas_keys(uint8_t *k_asme,
uint8_t *k_nas_enc,
uint8_t *k_nas_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// RRC interface
void generate_as_keys(uint32_t count_ul,
void generate_as_keys(uint8_t *k_asme,
uint32_t count_ul,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -100,13 +106,15 @@ private:
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res);
uint8_t *res,
uint8_t *k_asme);
void gen_auth_res_xor( uint8_t *rand,
uint8_t *autn_enb,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res);
uint8_t *res,
uint8_t *k_asme);
void str_to_hex(std::string str, uint8_t *hex);
srslte::log *usim_log;
@ -119,6 +127,9 @@ private:
uint64_t imei;
uint8_t k[16];
std::string imsi_str;
std::string imei_str;
// Security variables
uint8_t rand[16];
uint8_t ck[16];
@ -126,7 +137,6 @@ private:
uint8_t ak[6];
uint8_t mac[8];
uint8_t autn[16];
uint8_t k_asme[32];
uint8_t k_enb[32];
uint8_t k_enb_star[32];

View File

@ -319,7 +319,7 @@ void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, mac_interface_phy::
void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_interface_phy::tb_action_ul_t* action)
{
int tbs = ul_harq.get_current_tbs(tti);
ul_harq.new_grant_ul_ack(grant, ack, action);
ul_harq.new_grant_ul_ack(grant, &ack, action);
if (!ack) {
metrics.tx_errors++;
} else {

View File

@ -243,10 +243,8 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32
}
}
}
// Now allocate the SDUs from the RLC
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].sched_len != 0) {
log_h->info("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len);
allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len);
}
}
@ -296,8 +294,8 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz)
sched_len = *sdu_space;
}
log_h->info("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n",
ch->id, ch->buffer_len, sched_len, *sdu_space);
log_h->debug("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n",
ch->id, ch->buffer_len, sched_len, sdu_space?*sdu_space:0);
*sdu_space -= sched_len;
ch->buffer_len -= sched_len;
@ -320,16 +318,15 @@ bool mux::allocate_sdu(uint32_t lcid, srslte::sch_pdu* pdu_msg, int max_sdu_sz)
sdu_len = max_sdu_sz;
}
int sdu_space = pdu_msg->get_sdu_space();
if (sdu_len > sdu_space) {
if (sdu_len > sdu_space || max_sdu_sz < 0) {
sdu_len = sdu_space;
}
}
if (sdu_len > MIN_RLC_SDU_LEN) {
if (pdu_msg->new_subh()) { // there is space for a new subheader
int sdu_len2 = sdu_len;
sdu_len = pdu_msg->get()->set_sdu(lcid, sdu_len, rlc);
if (sdu_len > 0) { // new SDU could be added
Info("SDU: allocated lcid=%d, rlc_buffer=%d, allocated=%d/%d, max_sdu_sz=%d, remaining=%d\n",
Debug("SDU: allocated lcid=%d, rlc_buffer=%d, allocated=%d/%d, max_sdu_sz=%d, remaining=%d\n",
lcid, buffer_state, sdu_len, sdu_space, max_sdu_sz, pdu_msg->rem_size());
return true;
} else {

View File

@ -75,8 +75,12 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
("rf.device_args", bpo::value<string>(&args->rf.device_args)->default_value("auto"), "Front-end device arguments")
("rf.time_adv_nsamples", bpo::value<string>(&args->rf.time_adv_nsamples)->default_value("auto"),
"Transmission time advance")
("rf.burst_preamble_us", bpo::value<string>(&args->rf.burst_preamble)->default_value("auto"),
"Transmission time advance")
("rf.burst_preamble_us", bpo::value<string>(&args->rf.burst_preamble)->default_value("auto"), "Transmission time advance")
("rrc.feature_group", bpo::value<uint32_t>(&args->rrc.feature_group)->default_value(0xe6041c00), "Hex value of the featureGroupIndicators field in the"
"UECapabilityInformation message. Default 0xe6041c00")
("rrc.ue_category", bpo::value<string>(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)")
("pcap.enable", bpo::value<bool>(&args->pcap.enable)->default_value(false),
"Enable MAC packet captures for wireshark")
@ -134,10 +138,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<int>(&args->expert.phy.sync_cpu_affinity)->default_value(-1),
"index of the core used by the sync thread")
("expert.ue_category",
bpo::value<string>(&args->expert.ue_cateogry)->default_value("4"),
"UE Category (1 to 5)")
("expert.metrics_period_secs",
bpo::value<float>(&args->expert.metrics_period_secs)->default_value(1.0),
"Periodicity for metrics in seconds")
@ -203,7 +203,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
"Tolerance (in Hz) for digial CFO compensation.")
("expert.cfo_ema",
bpo::value<float>(&args->expert.phy.cfo_ema)->default_value(0.4),
bpo::value<float>(&args->expert.phy.cfo_ema)->default_value(0.3),
"CFO Exponential Moving Average coefficient. Lower makes it more robust to noise "
"but vulnerable to periodic interruptions due to VCO corrections.")
@ -369,6 +369,9 @@ int main(int argc, char *argv[])
srslte::metrics_hub<ue_metrics_t> metricshub;
signal(SIGINT, sig_int_handler);
all_args_t args;
srslte_debug_handle_crash(argc, argv);
parse_args(&args, argc, argv);
srsue_instance_type_t type = LTE;

View File

@ -43,8 +43,7 @@ int radio_recv_callback(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsampl
}
double callback_set_rx_gain(void *h, double gain) {
srslte::radio_multi *radio_handler = (srslte::radio_multi *) h;
return radio_handler->set_rx_gain_th(gain);
return ((phch_recv*) h)->set_rx_gain(gain);
}
@ -395,8 +394,6 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
current_earfcn = earfcn;
printf("cell select called set frequency\n");
if (set_frequency()) {
this->cell = cell;
log_h->info("Cell Select: Configuring cell...\n");
@ -519,6 +516,9 @@ int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s
}
}
double phch_recv::set_rx_gain(double gain) {
return radio_h->set_rx_gain_th(gain);
}

View File

@ -27,6 +27,7 @@
#include <unistd.h>
#include <string.h>
#include "phy/phch_worker.h"
#include "srslte/srslte.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/asn1/liblte_rrc.h"
@ -40,8 +41,6 @@
#ifdef ENABLE_GUI
#include "srsgui/srsgui.h"
#include <semaphore.h>
#include "srslte/srslte.h"
#include "srslte/interfaces/ue_interfaces.h"
void init_plots(srsue::phch_worker *worker);
pthread_t plot_thread;
@ -130,6 +129,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h)
srslte_ue_ul_set_normalization(&ue_ul, true);
srslte_ue_ul_set_cfo_enable(&ue_ul, true);
srslte_ue_ul_set_cfo_tol(&ue_ul, phy->args->cfo_correct_tol_hz);
mem_initiated = true;
@ -324,7 +324,7 @@ void phch_worker::work_imp()
ul_action.tti_offset = HARQ_DELAY_MS;
/* Send UL grant or HARQ information (from PHICH) to MAC */
if (ul_grant_available && ul_ack_available) {
if (ul_grant_available && ul_ack_available) {
phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action);
} else if (ul_grant_available && !ul_ack_available) {
phy->mac->new_grant_ul(ul_mac_grant, &ul_action);
@ -479,15 +479,19 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
return false;
}
grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS));
grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(UL_PIDOF(TTI_TX(tti)));
// Set last TBS for this TB (pid) in case of mcs>29 (7.1.7.2 of 36.213)
// Set last TBS for this TB (pid) in case of mcs>28 (7.1.7.2 of 36.213)
for (int i=0;i<SRSLTE_MAX_CODEWORDS;i++) {
if (grant->phy_grant.dl.mcs[i].tbs < 0) {
grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i];
if (grant->phy_grant.dl.mcs[i].idx > 28) {
grant->phy_grant.dl.mcs[i].tbs = phy->last_dl_tbs[grant->pid][i];
}
if(grant->phy_grant.dl.mcs[i].tbs < 0) {
Info("Invalid TBS size for PDSCH grant\n");
grant->phy_grant.dl.mcs[i].tbs = 0;
}
// save it
last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs;
phy->last_dl_tbs[grant->pid][i] = grant->phy_grant.dl.mcs[i].tbs;
}
/* Fill MAC grant structure */
@ -536,14 +540,19 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant->tb_en[tb] && (rv[tb] < 0 || rv[tb] > 3)) {
valid_config = false;
Error("Wrong RV (%d) for TB index %d", rv[tb], tb);
Error("Wrong RV (%d) for TB index %d\n", rv[tb], tb);
}
}
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
switch(phy->config->dedicated.antenna_info_explicit_value.tx_mode) {
/* Implemented Tx Modes */
case LIBLTE_RRC_TRANSMISSION_MODE_1:
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
if (nof_tb != 1) {
Error("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
valid_config = false;
}
break;
case LIBLTE_RRC_TRANSMISSION_MODE_2:
if (cell.nof_ports > 1) {
@ -551,26 +560,30 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
} else {
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
}
if (nof_tb != 1) {
Error("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
valid_config = false;
}
break;
case LIBLTE_RRC_TRANSMISSION_MODE_3:
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
if (nof_tb == 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
mimo_type = SRSLTE_MIMO_TYPE_CDD;
} else {
Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas,
SRSLTE_RA_DL_GRANT_NOF_TB(grant));
nof_tb);
valid_config = false;
}
break;
case LIBLTE_RRC_TRANSMISSION_MODE_4:
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
if (nof_tb == 1) {
mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} else {
Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas,
SRSLTE_RA_DL_GRANT_NOF_TB(grant));
nof_tb);
valid_config = false;
}
break;
@ -590,6 +603,19 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
valid_config = false;
}
/* Set power allocation according to 3GPP 36.213 clause 5.2 Downlink power allocation */
float rho_a = 1.0f, rho_b = 1.0f;
if (phy->config->dedicated.pdsch_cnfg_ded < LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) {
float rho_a_db = liblte_rrc_pdsch_config_p_a_num[(int) phy->config->dedicated.pdsch_cnfg_ded];
rho_a = powf(10.0f, rho_a_db / 20.0f) * ((cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f));
}
if (phy->config->common.pdsch_cnfg.p_b < 4) {
uint32_t idx0 = (cell.nof_ports == 1) ? 0 : 1;
float cell_specific_ratio = pdsch_cfg_cell_specific_ratio_table[idx0][phy->config->common.pdsch_cnfg.p_b];
rho_b = sqrtf(cell_specific_ratio);
}
srslte_ue_dl_set_power_alloc(&ue_dl, rho_a, rho_b);
Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti);
/* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */
@ -646,6 +672,9 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
Error("Error configuring DL grant\n");
ret = SRSLTE_ERROR;
}
} else {
Error("Error invalid DL config\n");
ret = SRSLTE_ERROR;
}
return ret;
}
@ -729,29 +758,30 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
}
}
// Handle Format0 adaptive retx
if (ret) {
// Use last TBS for this TB in case of mcs>28
if (grant->phy_grant.ul.mcs.tbs < 0) {
grant->phy_grant.ul.mcs.tbs = last_ul_tbs[tti%(2*HARQ_DELAY_MS)];
}
last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs;
if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_LAST) {
grant->phy_grant.ul.mcs.mod = last_ul_mod[tti%(2*HARQ_DELAY_MS)];
if (grant->phy_grant.ul.mcs.idx > 28) {
// Make sure we received a grant in the previous TTI for this PID
grant->phy_grant.ul.mcs.tbs = phy->last_ul_tbs[UL_PIDOF(TTI_TX(tti))];
grant->phy_grant.ul.mcs.mod = phy->last_ul_mod[UL_PIDOF(TTI_TX(tti))];
grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod);
}
last_ul_mod[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod;
}
/* Limit UL modulation if not supported by the UE or disabled by higher layers */
if (!phy->config->enable_64qam) {
if (grant->phy_grant.ul.mcs.mod >= SRSLTE_MOD_64QAM) {
grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM;
grant->phy_grant.ul.Qm = 4;
if (ret) {
phy->last_ul_tbs[UL_PIDOF(TTI_TX(tti))] = grant->phy_grant.ul.mcs.tbs;
phy->last_ul_mod[UL_PIDOF(TTI_TX(tti))] = grant->phy_grant.ul.mcs.mod;
phy->last_ul_tti[UL_PIDOF(TTI_TX(tti))] = TTI_RX_ACK(tti);
/* Limit UL modulation if not supported by the UE or disabled by higher layers */
if (!phy->config->enable_64qam) {
if (grant->phy_grant.ul.mcs.mod >= SRSLTE_MOD_64QAM) {
grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM;
grant->phy_grant.ul.Qm = 4;
}
}
}
/* Make sure the grant is valid */
if (ret && !srslte_dft_precoding_valid_prb(grant->phy_grant.ul.L_prb) && grant->phy_grant.ul.L_prb <= cell.nof_prb) {
Warning("Received invalid UL grant. L=%d\n", grant->phy_grant.ul.L_prb);
@ -768,11 +798,9 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &dci_unpacked, cell.nof_prb);
}
return true;
} else {
return false;
}
}
return ret;
}
void phch_worker::reset_uci()

View File

@ -199,9 +199,10 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) {
}
void phy::set_timeadv(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
//Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd);
sf_recv.set_time_adv_sec(((float) (new_nta - n_ta))*SRSLTE_LTE_TS);
Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6);
n_ta = new_nta;
}
void phy::configure_prach_params()

View File

@ -32,7 +32,6 @@
#include <string>
#include <algorithm>
#include <iterator>
#include <ue_base.h>
using namespace srslte;
@ -58,6 +57,7 @@ bool ue::init(all_args_t *args_)
} else {
logger_file.init(args->log.filename);
logger_file.log("\n\n");
logger_file.log(get_build_string().c_str());
logger = &logger_file;
}
@ -117,7 +117,11 @@ bool ue::init(all_args_t *args_)
// Init layers
// PHY initis in background, start before radio
if (args->rf.rx_gain < 0) {
phy.set_agc_enable(true);
}
// PHY initis in background, start before radio
args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant;
phy.init(&radio, &mac, &rrc, phy_log, &args->expert.phy);
@ -160,8 +164,6 @@ bool ue::init(all_args_t *args_)
if (args->rf.rx_gain < 0) {
radio.start_agc(false);
radio.set_tx_rx_gain_offset(10);
phy.set_agc_enable(true);
} else {
radio.set_rx_gain(args->rf.rx_gain);
}
@ -188,7 +190,12 @@ bool ue::init(all_args_t *args_)
gw.set_netmask(args->expert.ip_netmask);
rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log);
rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str()));
// Get current band from provided EARFCN
args->rrc.supported_bands[0] = srslte_band_get_band(args->rf.dl_earfcn);
args->rrc.nof_supported_bands = 1;
args->rrc.ue_category = atoi(args->ue_category_str.c_str());
rrc.set_args(&args->rrc);
// Currently EARFCN list is set to only one frequency as indicated in ue.conf
std::vector<uint32_t> earfcn_list;

View File

@ -24,13 +24,14 @@
*
*/
#include "ue_base.h"
#include "ue.h"
#include "srslte/srslte.h"
#include "srslte/build_info.h"
#include <pthread.h>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
@ -58,6 +59,9 @@ ue_base* ue_base::get_instance(srsue_instance_type_t type)
}
ue_base::ue_base() {
// print build info
std::cout << std::endl << get_build_string() << std::endl;
// load FFTW wisdom
srslte_dft_load();
}
@ -116,4 +120,21 @@ srslte::LOG_LEVEL_ENUM ue_base::level(std::string l)
}
}
std::string ue_base::get_build_mode()
{
return std::string(srslte_get_build_mode());
}
std::string ue_base::get_build_info()
{
return std::string(srslte_get_build_info());
}
std::string ue_base::get_build_string()
{
std::stringstream ss;
ss << "Built in " << get_build_mode() << " mode using " << get_build_info() << "." << std::endl;
return ss.str();
}
} // namespace srsue

View File

@ -25,6 +25,11 @@
*/
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include "srslte/asn1/liblte_rrc.h"
#include "upper/nas.h"
#include "srslte/common/bcd_helpers.h"
@ -33,9 +38,78 @@ using namespace srslte;
namespace srsue {
/*********************************************************************
* Conversion helpers
********************************************************************/
std::string hex_to_string(uint8_t *hex, int size)
{
std::stringstream ss;
ss << std::hex << std::setfill('0');
for(int i=0; i<size; i++) {
ss << std::setw(2) << static_cast<unsigned>(hex[i]);
}
return ss.str();
}
bool string_to_hex(std::string hex_str, uint8_t *hex, uint32_t len)
{
static const char* const lut = "0123456789abcdef";
uint32_t str_len = hex_str.length();
if(str_len & 1) {
return false; // uneven hex_str length
}
if(str_len > len*2) {
return false; // not enough space in hex buffer
}
for(uint32_t i=0; i<str_len; i+=2)
{
char a = hex_str[i];
const char* p = std::lower_bound(lut, lut + 16, a);
if (*p != a) {
return false; // invalid char
}
char b = hex_str[i+1];
const char* q = std::lower_bound(lut, lut + 16, b);
if (*q != b) {
return false; // invalid char
}
hex[i/2] = ((p - lut) << 4) | (q - lut);
}
return true;
}
std::string emm_info_str(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *info)
{
std::stringstream ss;
if(info->full_net_name_present) {
ss << info->full_net_name.name;
}
if(info->short_net_name_present) {
ss << " (" << info->short_net_name.name << ")";
}
if(info->utc_and_local_time_zone_present) {
ss << " " << (int)info->utc_and_local_time_zone.day;
ss << "/" << (int)info->utc_and_local_time_zone.month;
ss << "/" << (int)info->utc_and_local_time_zone.year;
ss << " " << (int)info->utc_and_local_time_zone.hour;
ss << ":" << (int)info->utc_and_local_time_zone.minute;
ss << ":" << (int)info->utc_and_local_time_zone.second;
ss << " TZ:" << (int)info->utc_and_local_time_zone.tz;
}
return ss.str();
}
nas::nas()
: state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), is_guti_set(false), ip_addr(0), eps_bearer_id(0),
count_ul(0), count_dl(0) {}
: state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), ip_addr(0), eps_bearer_id(0)
{
ctxt.rx_count = 0;
ctxt.tx_count = 0;
}
void nas::init(usim_interface_nas *usim_,
rrc_interface_nas *rrc_,
@ -51,15 +125,26 @@ void nas::init(usim_interface_nas *usim_,
state = EMM_STATE_DEREGISTERED;
plmn_selection = PLMN_NOT_SELECTED;
if (usim->get_home_plmn_id(&home_plmn)) {
if (!usim->get_home_plmn_id(&home_plmn)) {
nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n");
home_plmn.mcc = 61441; // This is 001
home_plmn.mnc = 65281; // This is 01
}
cfg = cfg_;
if((have_guti = read_guti_file(&guti))) {
if((have_ctxt = read_ctxt_file(&ctxt))) {
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int,
ctxt.cipher_algo, ctxt.integ_algo);
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int");
}
}
}
void nas::stop() {}
void nas::stop() {
write_ctxt_file(ctxt);
}
emm_state_t nas::get_state() {
return state;
@ -207,11 +292,11 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
}
uint32_t nas::get_ul_count() {
return count_ul;
return ctxt.tx_count;
}
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) {
if (is_guti_set) {
if (have_guti) {
s_tmsi->mmec = guti.mme_code;
s_tmsi->m_tmsi = guti.m_tmsi;
return true;
@ -220,11 +305,26 @@ bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) {
}
}
bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) {
if(!have_ctxt) {
nas_log->error("K_asme requested before security context established\n");
return false;
}
if(NULL == k_asme_ || n < 32) {
nas_log->error("Invalid parameters to get_k_asme");
return false;
}
memcpy(k_asme_, ctxt.k_asme, 32);
return true;
}
/*******************************************************************************
Security
*******************************************************************************/
void nas::integrity_generate(uint8_t *key_128,
void nas::integrity_generate(uint8_t integ_algo,
uint8_t *key_128,
uint32_t count,
uint8_t rb_id,
uint8_t direction,
@ -269,6 +369,16 @@ void nas::cipher_decrypt() {
}
bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps)
{
for(uint32_t i=0; i<8; i++) {
if(caps->eea[i] != eea_caps[i] || caps->eia[i] != eia_caps[i]) {
return false;
}
}
return true;
}
/*******************************************************************************
Parsers
@ -289,8 +399,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
//FIXME: Handle tai_list
if (attach_accept.guti_present) {
memcpy(&guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
is_guti_set = true;
// TODO: log message to console
have_guti = true;
write_guti_file(guti);
}
if (attach_accept.lai_present) {
}
@ -358,10 +468,9 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
state = EMM_STATE_REGISTERED;
current_plmn = selecting_plmn;
count_dl++;
ctxt.rx_count++;
// Send EPS bearer context accept and attach complete
count_ul++;
act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id;
act_def_eps_bearer_context_accept.proc_transaction_id = transaction_id;
act_def_eps_bearer_context_accept.protocol_cnfg_opts_present = false;
@ -369,10 +478,11 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
&attach_complete.esm_msg);
liblte_mme_pack_attach_complete_msg(&attach_complete,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
count_ul,
ctxt.tx_count,
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
integrity_generate(&k_nas_int[16],
count_ul,
integrity_generate(ctxt.integ_algo,
&k_nas_int[16],
ctxt.tx_count,
lcid - 1,
SECURITY_DIRECTION_UPLINK,
&pdu->msg[5],
@ -384,6 +494,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->info("Sending Attach Complete\n");
rrc->write_sdu(lcid, pdu);
ctxt.tx_count++;
} else {
nas_log->info("Not handling attach type %u\n", attach_accept.eps_attach_result);
@ -407,7 +518,7 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req;
LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res;
nas_log->info("Received Authentication Request\n");;
nas_log->info("Received Authentication Request\n");
liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &auth_req);
// Reuse the pdu for the response message
@ -422,7 +533,15 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
bool net_valid;
uint8_t res[16];
usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, &net_valid, res);
usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc,
&net_valid, res, ctxt.k_asme);
nas_log->info("Generated k_asme=%s\n", hex_to_string(ctxt.k_asme, 32).c_str());
if(LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE == auth_req.nas_ksi.tsc_flag) {
ctxt.ksi = auth_req.nas_ksi.nas_ksi;
} else {
nas_log->error("NAS mapped security context not currently supported\n");
nas_log->console("Warning: NAS mapped security context not currently supported\n");
}
if (net_valid) {
nas_log->info("Network authentication successful\n");
@ -438,9 +557,6 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->console("Warning: Network authentication failure\n");
pool->deallocate(pdu);
}
// Reset DL counter (as per 24.301 5.4.3.2)
count_dl = 0;
}
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) {
@ -451,107 +567,154 @@ void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) {
}
void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_identity_request\n");
LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req;
LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp;
liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &id_req);
nas_log->info("Received Identity Request. ID type: %d\n", id_req.id_type);
switch(id_req.id_type) {
case LIBLTE_MME_MOBILE_ID_TYPE_IMSI:
id_resp.mobile_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMSI;
usim->get_imsi_vec(id_resp.mobile_id.imsi, 15);
break;
case LIBLTE_MME_MOBILE_ID_TYPE_IMEI:
id_resp.mobile_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEI;
usim->get_imei_vec(id_resp.mobile_id.imei, 15);
break;
default:
nas_log->error("Unhandled ID type: %d\n");
pool->deallocate(pdu);
return;
}
pdu->reset();
liblte_mme_pack_identity_response_msg(&id_resp, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
rrc->write_sdu(lcid, pdu);
}
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) {
bool success;
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
{
LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd;
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp;
LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej;
nas_log->info("Received Security Mode Command\n");
liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &sec_mode_cmd);
nas_log->info("Received Security Mode Command ksi: %d, eea: %s, eia: %s\n",
sec_mode_cmd.nas_ksi.nas_ksi,
ciphering_algorithm_id_text[sec_mode_cmd.selected_nas_sec_algs.type_of_eea],
integrity_algorithm_id_text[sec_mode_cmd.selected_nas_sec_algs.type_of_eia]);
ksi = sec_mode_cmd.nas_ksi.nas_ksi;
cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eea;
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eia;
// FIXME: Handle nonce_ue, nonce_mme
// FIXME: Currently only handling ciphering EEA0 (null) and integrity EIA1,EIA2
// FIXME: Use selected_nas_sec_algs to choose correct algos
if(sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) {
nas_log->error("Mapped security context not supported\n");
pool->deallocate(pdu);
return;
}
nas_log->debug("Security details: ksi=%d, eea=%s, eia=%s\n",
ksi, ciphering_algorithm_id_text[cipher_algo], integrity_algorithm_id_text[integ_algo]);
if(sec_mode_cmd.nas_ksi.nas_ksi != ctxt.ksi)
{
nas_log->warning("Sending Security Mode Reject due to key set ID mismatch\n");
send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED);
pool->deallocate(pdu);
return;
}
// MME is setting up security context
// TODO: check nonce (not sent by Amari)
if (CIPHERING_ALGORITHM_ID_EEA0 != cipher_algo ||
(INTEGRITY_ALGORITHM_ID_128_EIA2 != integ_algo &&
INTEGRITY_ALGORITHM_ID_128_EIA1 != integ_algo) ||
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) {
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH;
// Check capabilities replay
if(!check_cap_replay(&sec_mode_cmd.ue_security_cap)) {
nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n");
success = false;
send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH);
pool->deallocate(pdu);
return;
}
// Reset counterd (as per 24.301 5.4.3.2)
ctxt.rx_count = 0;
ctxt.tx_count = 0;
ctxt.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eea;
ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eia;
// Check capabilities
if(!eea_caps[ctxt.cipher_algo] || !eia_caps[ctxt.integ_algo]) {
nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n");
send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH);
pool->deallocate(pdu);
return;
}
// Generate NAS keys
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo);
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int");
nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n",
ctxt.integ_algo, ctxt.rx_count, lcid);
// Check incoming MAC
uint8_t *inMAC = &pdu->msg[1];
uint8_t genMAC[4];
integrity_generate(ctxt.integ_algo,
&k_nas_int[16],
ctxt.rx_count,
lcid - 1,
SECURITY_DIRECTION_DOWNLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
genMAC);
nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:");
nas_log->info_hex(genMAC, 4, "Generated PDU MAC:");
ctxt.rx_count++;
bool match = true;
for (int i = 0; i < 4; i++) {
if (inMAC[i] != genMAC[i]) {
match = false;
}
}
if(!match) {
nas_log->warning("Sending Security Mode Reject due to integrity check failure\n");
send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED);
pool->deallocate(pdu);
return;
}
// Take security context into use
have_ctxt = true;
if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) {
sec_mode_comp.imeisv_present = true;
sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV;
usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15);
sec_mode_comp.imeisv.imeisv[14] = 5;
sec_mode_comp.imeisv.imeisv[15] = 3;
} else {
// Generate NAS encryption key and integrity protection key
usim->generate_nas_keys(k_nas_enc, k_nas_int, cipher_algo, integ_algo);
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int");
// Check incoming MAC
uint8_t *inMAC = &pdu->msg[1];
uint8_t genMAC[4];
integrity_generate(&k_nas_int[16],
count_dl,
lcid - 1,
SECURITY_DIRECTION_DOWNLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
genMAC);
nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:");
nas_log->info_hex(genMAC, 4, "Generated PDU MAC:");
bool match = true;
for (int i = 0; i < 4; i++) {
if (inMAC[i] != genMAC[i]) {
match = false;
}
}
if (!match) {
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED;
nas_log->warning("Sending Security Mode Reject due to integrity check failure\n");
success = false;
} else {
if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) {
sec_mode_comp.imeisv_present = true;
sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV;
usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15);
sec_mode_comp.imeisv.imeisv[14] = 5;
sec_mode_comp.imeisv.imeisv[15] = 3;
} else {
sec_mode_comp.imeisv_present = false;
}
// Reuse pdu for response
pdu->reset();
liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
count_ul,
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
integrity_generate(&k_nas_int[16],
count_ul,
lcid - 1,
SECURITY_DIRECTION_UPLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
&pdu->msg[1]);
nas_log->info("Sending Security Mode Complete nas_count_ul=%d, RB=%s\n",
count_ul,
rrc->get_rb_name(lcid).c_str());
success = true;
}
sec_mode_comp.imeisv_present = false;
}
count_dl++;
if (!success) {
// Reuse pdu for response
pdu->reset();
liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
}
rrc->write_sdu(lcid, pdu);
// Send response
byte_buffer_t *sdu = pool_allocate;
liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
ctxt.tx_count,
(LIBLTE_BYTE_MSG_STRUCT *) sdu);
integrity_generate(ctxt.integ_algo,
&k_nas_int[16],
ctxt.tx_count,
lcid - 1,
SECURITY_DIRECTION_UPLINK,
&sdu->msg[5],
sdu->N_bytes - 5,
&sdu->msg[1]);
nas_log->info("Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s\n",
ctxt.tx_count,
rrc->get_rb_name(lcid).c_str());
rrc->write_sdu(lcid, sdu);
ctxt.tx_count++;
pool->deallocate(pdu);
}
void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) {
@ -560,10 +723,15 @@ void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) {
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_esm_information_request\n");
}
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_emm_information\n");
liblte_mme_unpack_emm_information_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &emm_info);
std::string str = emm_info_str(&emm_info);
nas_log->info("Received EMM Information: %s\n", str.c_str());
nas_log->console("%s\n", str.c_str());
ctxt.rx_count++;
}
/*******************************************************************************
@ -578,25 +746,13 @@ void nas::send_attach_request() {
attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH;
for (i = 0; i < 8; i++) {
attach_req.ue_network_cap.eea[i] = false;
attach_req.ue_network_cap.eia[i] = false;
attach_req.ue_network_cap.eea[i] = eea_caps[i];
attach_req.ue_network_cap.eia[i] = eia_caps[i];
}
attach_req.ue_network_cap.eea[0] = true; // EEA0 supported
attach_req.ue_network_cap.eia[0] = true; // EIA0 supported
attach_req.ue_network_cap.eia[1] = true; // EIA1 supported
attach_req.ue_network_cap.eia[2] = true; // EIA2 supported
attach_req.ue_network_cap.uea_present = false; // UMTS encryption algos
attach_req.ue_network_cap.uia_present = false; // UMTS integrity algos
attach_req.ms_network_cap_present = false; // A/Gb mode (2G) or Iu mode (3G)
attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15);
// ESM message (PDN connectivity request) for first default bearer
gen_pdn_connectivity_request(&attach_req.esm_msg);
attach_req.ue_network_cap.uea_present = false; // UMTS encryption algos
attach_req.ue_network_cap.uia_present = false; // UMTS integrity algos
attach_req.ms_network_cap_present = false; // A/Gb mode (2G) or Iu mode (3G)
attach_req.old_p_tmsi_signature_present = false;
attach_req.additional_guti_present = false;
attach_req.last_visited_registered_tai_present = false;
@ -612,11 +768,47 @@ void nas::send_attach_request() {
attach_req.device_properties_present = false;
attach_req.old_guti_type_present = false;
// Pack the message
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg);
// ESM message (PDN connectivity request) for first default bearer
gen_pdn_connectivity_request(&attach_req.esm_msg);
// GUTI or IMSI attach
if(have_guti && have_ctxt) {
attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI;
memcpy(&attach_req.eps_mobile_id.guti, &guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
attach_req.old_guti_type = LIBLTE_MME_GUTI_TYPE_NATIVE;
attach_req.old_guti_type_present = true;
attach_req.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
attach_req.nas_ksi.nas_ksi = ctxt.ksi;
nas_log->info("Requesting GUTI attach. "
"m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n",
guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code);
liblte_mme_pack_attach_request_msg(&attach_req,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY,
ctxt.tx_count,
(LIBLTE_BYTE_MSG_STRUCT *) msg);
// Add MAC
integrity_generate(ctxt.integ_algo,
&k_nas_int[16],
ctxt.tx_count,
cfg.lcid-1,
SECURITY_DIRECTION_UPLINK,
&msg->msg[5],
msg->N_bytes - 5,
&msg->msg[1]);
} else {
attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15);
nas_log->info("Requesting IMSI attach. imsi: %s\n", usim->get_imsi_str());
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg);
}
nas_log->info("Sending attach request\n");
rrc->write_sdu(cfg.lcid, msg);
if(have_ctxt) {
ctxt.tx_count++;
}
}
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
@ -640,27 +832,36 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
liblte_mme_pack_pdn_connectivity_request_msg(&pdn_con_req, msg);
}
void nas::send_security_mode_reject(uint8_t cause) {
byte_buffer_t *msg = pool_allocate;
LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej;
sec_mode_rej.emm_cause = cause;
liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg);
rrc->write_sdu(cfg.lcid, msg);
}
void nas::send_identity_response() {}
void nas::send_service_request() {
byte_buffer_t *msg = pool_allocate;
count_ul++;
// Pack the service request message directly
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg->N_bytes++;
msg->msg[1] = (ksi & 0x07) << 5;
msg->msg[1] |= count_ul & 0x1F;
msg->msg[1] = (ctxt.ksi & 0x07) << 5;
msg->msg[1] |= ctxt.tx_count & 0x1F;
msg->N_bytes++;
uint8_t mac[4];
integrity_generate(&k_nas_int[16],
count_ul,
cfg.lcid-1,
SECURITY_DIRECTION_UPLINK,
&msg->msg[0],
2,
&mac[0]);
integrity_generate(ctxt.integ_algo,
&k_nas_int[16],
ctxt.tx_count,
cfg.lcid-1,
SECURITY_DIRECTION_UPLINK,
&msg->msg[0],
2,
&mac[0]);
// Set the short MAC
msg->msg[2] = mac[2];
msg->N_bytes++;
@ -668,8 +869,239 @@ void nas::send_service_request() {
msg->N_bytes++;
nas_log->info("Sending service request\n");
rrc->write_sdu(cfg.lcid, msg);
ctxt.tx_count++;
}
void nas::send_esm_information_response() {}
bool nas::read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti)
{
std::ifstream file;
std::string line;
if (!guti) {
return false;
}
const char *m_tmsi_str = "m_tmsi=";
size_t m_tmsi_str_len = strlen(m_tmsi_str);
const char *mcc_str = "mcc=";
size_t mcc_str_len = strlen(mcc_str);
const char *mnc_str = "mnc=";
size_t mnc_str_len = strlen(mnc_str);
const char *mme_group_id_str = "mme_group_id=";
size_t mme_group_id_str_len = strlen(mme_group_id_str);
const char *mme_code_str = "mme_code=";
size_t mme_code_str_len = strlen(mme_code_str);
file.open(".guti", std::ios::in);
if (file.is_open()) {
bool read_ok = true;
if (std::getline(file, line)) {
if (!line.substr(0,m_tmsi_str_len).compare(m_tmsi_str)) {
guti->m_tmsi = atoi(line.substr(m_tmsi_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,mcc_str_len).compare(mcc_str)) {
guti->mcc = atoi(line.substr(mcc_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,mnc_str_len).compare(mnc_str)) {
guti->mnc = atoi(line.substr(mnc_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,mme_group_id_str_len).compare(mme_group_id_str)) {
guti->mme_group_id = atoi(line.substr(mme_group_id_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,mme_code_str_len).compare(mme_code_str)) {
guti->mme_code = atoi(line.substr(mme_code_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
file.close();
if (read_ok) {
nas_log->info("Read GUTI from file .guti. "
"m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n",
guti->m_tmsi, guti->mcc, guti->mnc, guti->mme_group_id, guti->mme_code);
return true;
} else {
nas_log->error("Invalid GUTI file format\n");
return false;
}
} else {
return false;
}
}
bool nas::write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti) {
std::ofstream file;
if (!have_guti) {
return false;
}
file.open(".guti", std::ios::out | std::ios::trunc);
if (file.is_open()) {
file << "m_tmsi=" << (int) guti.m_tmsi << std::endl;
file << "mcc=" << (int) guti.mcc << std::endl;
file << "mnc=" << (int) guti.mnc << std::endl;
file << "mme_group_id=" << (int) guti.mme_group_id << std::endl;
file << "mme_code=" << (int) guti.mme_code << std::endl;
nas_log->info("Saved GUTI to file .guti. "
"m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n",
guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code);
file.close();
return true;
} else {
return false;
}
}
bool nas::read_ctxt_file(nas_sec_ctxt *ctxt)
{
std::ifstream file;
std::string line;
if (!ctxt) {
return false;
}
const char *ksi_str = "ksi=";
size_t ksi_str_len = strlen(ksi_str);
const char *k_asme_str = "k_asme=";
size_t k_asme_str_len = strlen(k_asme_str);
const char *tx_count_str = "tx_count=";
size_t tx_count_str_len = strlen(tx_count_str);
const char *rx_count_str = "rx_count=";
size_t rx_count_str_len = strlen(rx_count_str);
const char *int_alg_str = "int_alg=";
size_t int_alg_str_len = strlen(int_alg_str);
const char *enc_alg_str = "enc_alg=";
size_t enc_alg_str_len = strlen(enc_alg_str);
file.open(".ctxt", std::ios::in);
if (file.is_open()) {
bool read_ok = true;
if (std::getline(file, line)) {
if (!line.substr(0,ksi_str_len).compare(ksi_str)) {
ctxt->ksi = atoi(line.substr(ksi_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,k_asme_str_len).compare(k_asme_str)) {
std::string tmp = line.substr(k_asme_str_len);
if(!string_to_hex(tmp, ctxt->k_asme, 32)) {
read_ok = false;
}
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,tx_count_str_len).compare(tx_count_str)) {
ctxt->tx_count = atoi(line.substr(tx_count_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,rx_count_str_len).compare(rx_count_str)) {
ctxt->rx_count = atoi(line.substr(rx_count_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,int_alg_str_len).compare(int_alg_str)) {
ctxt->integ_algo = (srslte::INTEGRITY_ALGORITHM_ID_ENUM)atoi(line.substr(int_alg_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
if (std::getline(file, line)) {
if (!line.substr(0,enc_alg_str_len).compare(enc_alg_str)) {
ctxt->cipher_algo = (srslte::CIPHERING_ALGORITHM_ID_ENUM)atoi(line.substr(enc_alg_str_len).c_str());
} else {
read_ok = false;
}
} else {
read_ok = false;
}
file.close();
if (read_ok) {
nas_log->info("Read security ctxt from file .ctxt. "
"ksi: %x, k_asme: %s, "
"tx_count: %x, rx_count: %x, "
"int_alg: %d, enc_alg: %d\n",
ctxt->ksi, hex_to_string(ctxt->k_asme,32).c_str(),
ctxt->tx_count, ctxt->rx_count,
ctxt->integ_algo, ctxt->cipher_algo);
return true;
} else {
nas_log->error("Invalid security ctxt file format\n");
return false;
}
} else {
return false;
}
}
bool nas::write_ctxt_file(nas_sec_ctxt ctxt)
{
std::ofstream file;
file.open(".ctxt", std::ios::out | std::ios::trunc);
if (file.is_open()) {
file << "ksi=" << (int) ctxt.ksi << std::endl;
file << "k_asme=" << hex_to_string(ctxt.k_asme, 32) << std::endl;
file << "tx_count=" << (int) ctxt.tx_count << std::endl;
file << "rx_count=" << (int) ctxt.rx_count << std::endl;
file << "int_alg=" << (int) ctxt.integ_algo << std::endl;
file << "enc_alg=" << (int) ctxt.cipher_algo << std::endl;
nas_log->info("Saved security ctxt to file .ctxt. "
"ksi: %x, k_asme: %s, "
"tx_count: %x, rx_count: %x, "
"int_alg: %d, enc_alg: %d\n",
ctxt.ksi, hex_to_string(ctxt.k_asme,32).c_str(),
ctxt.tx_count, ctxt.rx_count,
ctxt.integ_algo, ctxt.cipher_algo);
file.close();
return true;
} else {
return false;
}
}
} // namespace srsue

View File

@ -26,12 +26,12 @@
#include <unistd.h>
#include <iostream>
#include <sstream>
#include "srslte/asn1/liblte_rrc.h"
#include <stdlib.h>
#include <time.h>
#include "upper/rrc.h"
#include <boost/assign.hpp>
#include <upper/rrc.h>
#include <srslte/asn1/liblte_rrc.h>
#include "srslte/asn1/liblte_rrc.h"
#include "srslte/common/security.h"
#include "srslte/common/bcd_helpers.h"
@ -48,6 +48,9 @@ rrc::rrc()
:state(RRC_STATE_IDLE)
,drb_up(false)
{
sync_reset_cnt = 0;
n310_cnt = 0;
n311_cnt = 0;
}
static void liblte_rrc_handler(void *ctx, char *str) {
@ -90,9 +93,14 @@ void rrc::init(phy_interface_rrc *phy_,
pthread_mutex_init(&mutex, NULL);
first_stimsi_attempt = false;
reestablishment_in_progress = false;
ue_category = SRSLTE_UE_CATEGORY;
args.ue_category = SRSLTE_UE_CATEGORY;
args.supported_bands[0] = 7;
args.nof_supported_bands = 1;
args.feature_group = 0xe6041c00;
t301 = mac_timers->timer_get_unique_id();
t310 = mac_timers->timer_get_unique_id();
t311 = mac_timers->timer_get_unique_id();
@ -114,6 +122,8 @@ void rrc::init(phy_interface_rrc *phy_,
set_mac_default();
measurements.init(this);
// set seed for rand (used in attach)
srand(time(NULL));
}
void rrc::stop() {
@ -137,12 +147,8 @@ bool rrc::have_drb() {
return drb_up;
}
void rrc::set_ue_category(int category) {
if (category >= 1 && category <= 5) {
ue_category = category;
} else {
rrc_log->error("Unsupported UE category %d\n", category);
}
void rrc::set_args(rrc_args_t *args) {
memcpy(&this->args, args, sizeof(rrc_args_t));
}
/*
@ -527,13 +533,17 @@ void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) {
// Detection of physical layer problems (5.3.11.1)
void rrc::out_of_sync() {
// attempt resync
sync_reset_cnt++;
if (sync_reset_cnt >= SYNC_RESET_TIMEOUT) {
rrc_log->info("Detected %d out-of-sync from PHY. Resynchronizing PHY.\n", sync_reset_cnt);
phy->sync_reset();
sync_reset_cnt = 0;
}
current_cell->in_sync = false;
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
n310_cnt++;
if (n310_cnt == N310) {
// attempt resync
//phy->sync_reset();
mac_timers->timer_get(t310)->reset();
mac_timers->timer_get(t310)->run();
n310_cnt = 0;
@ -632,13 +642,15 @@ void rrc::send_con_request() {
// Prepare ConnectionRequest packet
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
if (nas->get_s_tmsi(&s_tmsi)) {
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI;
ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi;
} else {
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000;
ul_ccch_msg.msg.rrc_con_req.ue_id.random = rand() % 2^40;
}
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
@ -1082,10 +1094,12 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) {
LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi_paged;
for (uint32_t i = 0; i < pcch_msg.paging_record_list_size; i++) {
s_tmsi_paged = &pcch_msg.paging_record_list[i].ue_identity.s_tmsi;
rrc_log->info("Received paging (%d/%d) for UE 0x%x\n", i + 1, pcch_msg.paging_record_list_size,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi);
rrc_log->console("Received paging (%d/%d) for UE 0x%x\n", i + 1, pcch_msg.paging_record_list_size,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi);
rrc_log->info("Received paging (%d/%d) for UE %x:%x\n", i + 1, pcch_msg.paging_record_list_size,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi);
rrc_log->console("Received paging (%d/%d) for UE %x:%x\n", i + 1, pcch_msg.paging_record_list_size,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec,
pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi);
if (s_tmsi.mmec == s_tmsi_paged->mmec && s_tmsi.m_tmsi == s_tmsi_paged->m_tmsi) {
rrc_log->info("S-TMSI match in paging message\n");
rrc_log->console("S-TMSI match in paging message\n");
@ -1244,7 +1258,9 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) dl_dcch_msg.msg.security_mode_cmd.sec_algs.int_alg;
// Configure PDCP for security
usim->generate_as_keys(nas->get_ul_count(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
uint8_t k_asme[32];
nas->get_k_asme(k_asme, 32);
usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo);
send_security_mode_complete(lcid, pdu);
break;
@ -1287,7 +1303,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
*
*******************************************************************************/
void rrc::enable_capabilities() {
bool enable_ul_64 = ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam;
bool enable_ul_64 = args.ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam;
rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling");
phy->set_config_64qam_en(enable_ul_64);
}
@ -1305,7 +1321,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *cap = &info->ue_capability_rat[0].eutra_capability;
cap->access_stratum_release = LIBLTE_RRC_ACCESS_STRATUM_RELEASE_REL8;
cap->ue_category = ue_category;
cap->ue_category = args.ue_category;
cap->pdcp_params.max_rohc_ctxts_present = false;
cap->pdcp_params.supported_rohc_profiles[0] = false;
@ -1321,31 +1337,17 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
cap->phy_params.specific_ref_sigs_supported = false;
cap->phy_params.tx_antenna_selection_supported = false;
//TODO: Generate this from user input?
cap->rf_params.N_supported_band_eutras = 3;
cap->rf_params.supported_band_eutra[0].band_eutra = 3;
cap->rf_params.supported_band_eutra[0].half_duplex = false;
cap->rf_params.supported_band_eutra[1].band_eutra = 7;
cap->rf_params.supported_band_eutra[1].half_duplex = false;
cap->rf_params.supported_band_eutra[2].band_eutra = 20;
cap->rf_params.supported_band_eutra[2].half_duplex = false;
cap->meas_params.N_band_list_eutra = 3;
cap->meas_params.band_list_eutra[0].N_inter_freq_need_for_gaps = 3;
cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[0] = true;
cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[1] = true;
cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[2] = true;
cap->meas_params.band_list_eutra[1].N_inter_freq_need_for_gaps = 3;
cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[0] = true;
cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[1] = true;
cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[2] = true;
cap->meas_params.band_list_eutra[2].N_inter_freq_need_for_gaps = 3;
cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[0] = true;
cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[1] = true;
cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[2] = true;
cap->rf_params.N_supported_band_eutras = args.nof_supported_bands;
cap->meas_params.N_band_list_eutra = args.nof_supported_bands;
for (uint32_t i=0;i<args.nof_supported_bands;i++) {
cap->rf_params.supported_band_eutra[i].band_eutra = args.supported_bands[i];
cap->rf_params.supported_band_eutra[i].half_duplex = false;
cap->meas_params.band_list_eutra[i].N_inter_freq_need_for_gaps = 1;
cap->meas_params.band_list_eutra[i].inter_freq_need_for_gaps[0] = true;
}
cap->feature_group_indicator_present = true;
cap->feature_group_indicator = 0x62001000;
cap->feature_group_indicator = args.feature_group;
cap->inter_rat_params.utra_fdd_present = false;
cap->inter_rat_params.utra_tdd128_present = false;
cap->inter_rat_params.utra_tdd384_present = false;
@ -1607,8 +1609,10 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
}
if (phy_cnfg->pdsch_cnfg_ded_present) {
current_cfg->pdsch_cnfg_ded = phy_cnfg->pdsch_cnfg_ded;
rrc_log->info("Set PDSCH-Config=%s (present)\n", liblte_rrc_pdsch_config_p_a_text[(int) current_cfg->pdsch_cnfg_ded]);
} else if (apply_defaults) {
current_cfg->pdsch_cnfg_ded = LIBLTE_RRC_PDSCH_CONFIG_P_A_DB_0;
rrc_log->info("Set PDSCH-Config=%s (default)\n", liblte_rrc_pdsch_config_p_a_text[(int) current_cfg->pdsch_cnfg_ded]);
}
if (phy_cnfg->cqi_report_cnfg_present) {

View File

@ -39,9 +39,11 @@ usim::usim() : initiated(false)
void usim::init(usim_args_t *args, srslte::log *usim_log_)
{
usim_log = usim_log_;
imsi_str = args->imsi;
imei_str = args->imei;
const char *imsi_str = args->imsi.c_str();
const char *imei_str = args->imei.c_str();
const char *imsi_c = args->imsi.c_str();
const char *imei_c = args->imei.c_str();
uint32_t i;
if(32 == args->op.length()) {
@ -63,7 +65,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_)
for(i=0; i<15; i++)
{
imsi *= 10;
imsi += imsi_str[i] - '0';
imsi += imsi_c[i] - '0';
}
} else {
usim_log->error("Invalid length for ISMI: %d should be %d", args->imsi.length(), 15);
@ -75,7 +77,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_)
for(i=0; i<15; i++)
{
imei *= 10;
imei += imei_str[i] - '0';
imei += imei_c[i] - '0';
}
} else {
usim_log->error("Invalid length for IMEI: %d should be %d", args->imei.length(), 15);
@ -103,16 +105,25 @@ void usim::stop()
NAS interface
*******************************************************************************/
void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n)
std::string usim::get_imsi_str()
{
return imsi_str;
}
std::string usim::get_imei_str()
{
return imei_str;
}
bool usim::get_imsi_vec(uint8_t* imsi_, uint32_t n)
{
if (!initiated) {
fprintf(stderr, "USIM not initiated!\n");
return;
return false;
}
if(NULL == imsi_ || n < 15) {
usim_log->error("Invalid parameters to get_imsi_vec");
return;
return false;
}
uint64_t temp = imsi;
@ -120,18 +131,19 @@ void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n)
imsi_[i] = temp % 10;
temp /= 10;
}
return true;
}
void usim::get_imei_vec(uint8_t* imei_, uint32_t n)
bool usim::get_imei_vec(uint8_t* imei_, uint32_t n)
{
if (!initiated) {
fprintf(stderr, "USIM not initiated!\n");
return;
return false;
}
if(NULL == imei_ || n < 15) {
usim_log->error("Invalid parameters to get_imei_vec");
return;
return false;
}
uint64 temp = imei;
@ -140,13 +152,14 @@ void usim::get_imei_vec(uint8_t* imei_, uint32_t n)
imei_[i] = temp % 10;
temp /= 10;
}
return true;
}
int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
bool usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
{
if (!initiated) {
fprintf(stderr, "USIM not initiated!\n");
return -1;
return false;
}
int mcc_len = 3;
@ -180,7 +193,7 @@ int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
usim_log->info("Read Home PLMN Id=%s\n",
plmn_id_to_string(*home_plmn_id).c_str());
return 0;
return true;
}
void usim::generate_authentication_response(uint8_t *rand,
@ -188,16 +201,18 @@ void usim::generate_authentication_response(uint8_t *rand,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res)
uint8_t *res,
uint8_t *k_asme)
{
if(auth_algo_xor == auth_algo) {
gen_auth_res_xor(rand, autn_enb, mcc, mnc, net_valid, res);
gen_auth_res_xor(rand, autn_enb, mcc, mnc, net_valid, res, k_asme);
} else {
gen_auth_res_milenage(rand, autn_enb, mcc, mnc, net_valid, res);
gen_auth_res_milenage(rand, autn_enb, mcc, mnc, net_valid, res, k_asme);
}
}
void usim::generate_nas_keys(uint8_t *k_nas_enc,
void usim::generate_nas_keys(uint8_t *k_asme,
uint8_t *k_nas_enc,
uint8_t *k_nas_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
@ -214,7 +229,8 @@ void usim::generate_nas_keys(uint8_t *k_nas_enc,
RRC interface
*******************************************************************************/
void usim::generate_as_keys(uint32_t count_ul,
void usim::generate_as_keys(uint8_t *k_asme,
uint32_t count_ul,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -285,7 +301,8 @@ void usim::gen_auth_res_milenage( uint8_t *rand,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res)
uint8_t *res,
uint8_t *k_asme)
{
uint32_t i;
uint8_t sqn[6];
@ -354,7 +371,8 @@ void usim::gen_auth_res_xor(uint8_t *rand,
uint16_t mcc,
uint16_t mnc,
bool *net_valid,
uint8_t *res)
uint8_t *res,
uint8_t *k_asme)
{
uint32_t i;
uint8_t sqn[6];

View File

@ -61,6 +61,7 @@ KASME : a8.27.57.5e.ea.1a.10.17.3a.a1.bf.ce.4b.0c.21.85.e0.51.ef.bd.91.7f.fe.f
uint8_t rand_enb[] = {0x88, 0x38, 0xc3, 0x55, 0xc8, 0x78, 0xaa, 0x57, 0x21, 0x49, 0xfe, 0x69, 0xdb, 0x68, 0x6b, 0x5a};
uint8_t autn_enb[] = {0xd7, 0x44, 0x51, 0x9b, 0x25, 0xaa, 0x80, 0x00, 0x84, 0xba, 0x37, 0xb0, 0xf6, 0x73, 0x4d, 0xd1};
uint8_t kasme[] = {0xa8, 0x27, 0x57, 0x5e, 0xea, 0x1a, 0x10, 0x17, 0x3a, 0xa1, 0xbf, 0xce, 0x4b, 0x0c, 0x21, 0x85, 0xe0, 0x51, 0xef, 0xbd, 0x91, 0x7f, 0xfe, 0xf5, 0x1f, 0x74, 0x29, 0x61, 0xf9, 0x03, 0x7a, 0x35};
uint16 mcc = 208;
uint16 mnc = 93;
@ -74,14 +75,14 @@ int main(int argc, char **argv)
usim_args_t args;
args.algo = "milenage";
args.amf = "8000";
args.imei = "35609204079301";
args.imei = "356092040793011";
args.imsi = "208930000000001";
args.k = "8BAF473F2F8FD09487CCCBD7097C6862";
args.op = "11111111111111111111111111111111";
srsue::usim usim;
usim.init(&args, &usim_log);
usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res);
usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res, kasme);
assert(net_valid == true);
}

View File

@ -92,19 +92,36 @@ k = 00112233445566778899aabbccddeeff
imsi = 001010123456789
imei = 353490069873319
#####################################################################
# RRC configuration
#
# stimsi_attach: If enabled, always tries first an S-TMSI attach using the
# S-TMSI value stored in .stimsi file generated in previous run
# mmec_value: If defined (non-zero), overwrites the value stored in .stimsi file
# m_tmsi_value: If defined (non-zero), overwrites the value stored in .stimsi file
#
# ue_category: Sets UE category (range 1-5). Default: 4
# feature_group: Hex value of the featureGroupIndicators field in the
# UECapabilityInformation message. Default 0xe6041c00
#####################################################################
[rrc]
#stmsi_attach = false
#mmec_value = 0
#mtmsi_value = 0
#ue_category = 4
#feature_group = 0xe6041c00
[gui]
enable = false
#####################################################################
# Expert configuration options
#
# ue_category: Sets UE category (range 1-5). Default: 4
# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0
# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but
# can cause UHD instability for long-duration testing. Default true.
# ue_category: Sets UE category (range 1-5). Default: 4
#
# prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,
# prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,
# Default is to use tx_gain in [rf] section.
# cqi_max: Upper bound on the maximum CQI to be reported. Default 15.
# cqi_fixed: Fixes the reported CQI to a constant value. Default disabled.
@ -146,7 +163,6 @@ enable = false
[expert]
#ip_netmask = 255.255.255.0
#rssi_sensor_enabled = false
#ue_category = 4
#prach_gain = 30
#cqi_max = 15
#cqi_fixed = 10
@ -156,7 +172,7 @@ enable = false
#attach_enable_64qam = false
#nof_phy_threads = 2
#equalizer_mode = mmse
#cfo_ema = 0.4
#cfo_ema = 0.3
#cfo_integer_enabled = false
#cfo_correct_tol_hz = 50
#time_correct_period = 5