Merging next into op_vs_opc and resolving conflicts.
This commit is contained in:
commit
f301bb6373
|
@ -599,7 +599,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
if (prog_args.rf_gain < 0) {
|
||||
if (prog_args.rf_gain < 0 && !prog_args.input_file_name) {
|
||||
srslte_rf_info_t *rf_info = srslte_rf_get_info(&rf);
|
||||
srslte_ue_sync_start_agc(&ue_sync,
|
||||
srslte_rf_set_rx_gain_th_wrapper_,
|
||||
|
|
|
@ -38,17 +38,19 @@ namespace srslte {
|
|||
class srslte_nas_config_t
|
||||
{
|
||||
public:
|
||||
srslte_nas_config_t(uint32_t lcid_ = 0, std::string apn_ = "", std::string user_ = "", std::string pass_ = "")
|
||||
srslte_nas_config_t(uint32_t lcid_ = 0, std::string apn_ = "", std::string user_ = "", std::string pass_ = "", bool force_imsi_attach_ = false)
|
||||
:lcid(lcid_),
|
||||
apn(apn_),
|
||||
user(user_),
|
||||
pass(pass_)
|
||||
pass(pass_),
|
||||
force_imsi_attach(force_imsi_attach_)
|
||||
{}
|
||||
|
||||
uint32_t lcid;
|
||||
std::string apn;
|
||||
std::string user;
|
||||
std::string pass;
|
||||
bool force_imsi_attach;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -274,8 +274,8 @@ public:
|
|||
class s1ap_interface_rrc
|
||||
{
|
||||
public:
|
||||
virtual void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu) = 0;
|
||||
virtual void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec) = 0;
|
||||
virtual void initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu) = 0;
|
||||
virtual void initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec) = 0;
|
||||
virtual void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu) = 0;
|
||||
virtual bool user_exists(uint16_t rnti) = 0;
|
||||
virtual bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) = 0;
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#define SRSLTE_CQI_MAX_BITS 64
|
||||
#define SRSLTE_DIF_CQI_MAX_BITS 3
|
||||
#define SRSLTE_PMI_MAX_BITS 4
|
||||
#define SRSLTE_CQI_STR_MAX_CHAR 32
|
||||
#define SRSLTE_CQI_STR_MAX_CHAR 64
|
||||
|
||||
typedef struct {
|
||||
bool configured;
|
||||
|
@ -150,6 +150,9 @@ SRSLTE_API int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg
|
|||
SRSLTE_API int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
|
||||
srslte_cqi_value_t *value);
|
||||
|
||||
SRSLTE_API int srslte_cqi_value_tostring(srslte_cqi_value_t *value, char *buff, uint32_t buff_len);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
|
||||
srslte_cqi_hl_subband_t *msg);
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ namespace srslte {
|
|||
class radio_multi : public radio
|
||||
{
|
||||
public:
|
||||
|
||||
radio_multi() {}
|
||||
~radio_multi() {}
|
||||
bool init_multi(uint32_t nof_rx_antennas, char *args = NULL, char *devname = NULL);
|
||||
bool rx_now(cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time);
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,7 +37,7 @@
|
|||
#include "srslte/common/liblte_security.h"
|
||||
#include "srslte/common/liblte_ssl.h"
|
||||
#include "math.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*******************************************************************************
|
||||
DEFINES
|
||||
*******************************************************************************/
|
||||
|
|
|
@ -81,7 +81,6 @@ thread_pool::thread_pool(uint32_t max_workers_) :
|
|||
status(max_workers_),
|
||||
cvar(max_workers_),
|
||||
mutex(max_workers_)
|
||||
|
||||
{
|
||||
max_workers = max_workers_;
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
|
|
|
@ -66,7 +66,7 @@ int srslte_timestamp_sub(srslte_timestamp_t *t, time_t full_secs, double frac_se
|
|||
t->frac_secs -= frac_secs;
|
||||
t->full_secs -= full_secs;
|
||||
if(t->frac_secs < 0){
|
||||
t->frac_secs = 1-t->frac_secs;
|
||||
t->frac_secs = t->frac_secs + 1;
|
||||
t->full_secs--;
|
||||
}
|
||||
if(t->full_secs < 0)
|
||||
|
|
|
@ -388,7 +388,7 @@ void srslte_enb_dl_put_mbsfn_base(srslte_enb_dl_t *q, uint32_t tti)
|
|||
void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q)
|
||||
{
|
||||
// TODO: PAPR control
|
||||
float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft[0].symbol_sz);
|
||||
float norm_factor = 0.05f / sqrt(q->cell.nof_prb);
|
||||
for (int i = 0; i < q->cell.nof_ports; i++) {
|
||||
srslte_ofdm_tx_sf(&q->ifft[i]);
|
||||
srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
|
||||
|
@ -397,7 +397,7 @@ void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q)
|
|||
|
||||
void srslte_enb_dl_gen_signal_mbsfn(srslte_enb_dl_t *q)
|
||||
{
|
||||
float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft_mbsfn.symbol_sz);
|
||||
float norm_factor = 0.05f / sqrt(q->cell.nof_prb);
|
||||
srslte_ofdm_tx_sf(&q->ifft_mbsfn);
|
||||
srslte_vec_sc_prod_cfc(q->ifft_mbsfn.out_buffer, norm_factor, q->ifft_mbsfn.out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant,
|
|||
srslte_dci_format_t format, srslte_dci_location_t location,
|
||||
uint16_t rnti, uint32_t sf_idx)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg;
|
||||
srslte_dci_msg_t dci_msg = {};
|
||||
|
||||
bool rnti_is_user = true;
|
||||
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
|
||||
|
@ -436,7 +436,7 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
|
|||
srslte_dci_location_t location,
|
||||
uint16_t rnti, uint32_t sf_idx)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg;
|
||||
srslte_dci_msg_t dci_msg = {};
|
||||
|
||||
srslte_dci_msg_pack_pusch(grant, &dci_msg, q->cell.nof_prb);
|
||||
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
|
||||
|
|
|
@ -234,6 +234,87 @@ int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*******************************************************
|
||||
* TO STRING FUNCTIONS *
|
||||
*******************************************************/
|
||||
|
||||
static int srslte_cqi_format2_wideband_tostring(srslte_cqi_format2_wideband_t *msg, char *buff, uint32_t buff_len) {
|
||||
int n = 0;
|
||||
|
||||
n += snprintf(buff + n, buff_len - n, ", cqi=%d", msg->wideband_cqi);
|
||||
|
||||
if (msg->pmi_present) {
|
||||
if (msg->rank_is_not_one) {
|
||||
n += snprintf(buff + n, buff_len - n, ", diff_cqi=%d", msg->spatial_diff_cqi);
|
||||
}
|
||||
n += snprintf(buff + n, buff_len - n, ", pmi=%d", msg->pmi);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int srslte_cqi_format2_subband_tostring(srslte_cqi_format2_subband_t *msg, char *buff, uint32_t buff_len) {
|
||||
int n = 0;
|
||||
|
||||
n += snprintf(buff + n, buff_len - n, ", cqi=%d", msg->subband_cqi);
|
||||
n += snprintf(buff + n, buff_len - n, ", label=%d", msg->subband_label);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int srslte_cqi_ue_subband_tostring(srslte_cqi_ue_subband_t *msg, char *buff, uint32_t buff_len) {
|
||||
int n = 0;
|
||||
|
||||
n += snprintf(buff + n, buff_len - n, ", cqi=%d", msg->wideband_cqi);
|
||||
n += snprintf(buff + n, buff_len - n, ", diff_cqi=%d", msg->subband_diff_cqi);
|
||||
n += snprintf(buff + n, buff_len - n, ", L=%d", msg->L);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int srslte_cqi_hl_subband_tostring(srslte_cqi_hl_subband_t *msg, char *buff, uint32_t buff_len) {
|
||||
int n = 0;
|
||||
|
||||
n += snprintf(buff + n, buff_len - n, ", cqi=%d", msg->wideband_cqi_cw0);
|
||||
n += snprintf(buff + n, buff_len - n, ", diff=%d", msg->subband_diff_cqi_cw0);
|
||||
|
||||
if (msg->rank_is_not_one) {
|
||||
n += snprintf(buff + n, buff_len - n, ", cqi1=%d", msg->wideband_cqi_cw1);
|
||||
n += snprintf(buff + n, buff_len - n, ", diff1=%d", msg->subband_diff_cqi_cw1);
|
||||
}
|
||||
|
||||
if (msg->pmi_present) {
|
||||
n += snprintf(buff + n, buff_len - n, ", pmi=%d", msg->pmi);
|
||||
}
|
||||
|
||||
n += snprintf(buff + n, buff_len - n, ", N=%d", msg->N);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int srslte_cqi_value_tostring(srslte_cqi_value_t *value, char *buff, uint32_t buff_len) {
|
||||
int ret = -1;
|
||||
|
||||
switch (value->type) {
|
||||
case SRSLTE_CQI_TYPE_WIDEBAND:
|
||||
ret = srslte_cqi_format2_wideband_tostring(&value->wideband, buff, buff_len);
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND:
|
||||
ret = srslte_cqi_format2_subband_tostring(&value->subband, buff, buff_len);
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND_UE:
|
||||
ret = srslte_cqi_ue_subband_tostring(&value->subband_ue, buff, buff_len);
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND_HL:
|
||||
ret = srslte_cqi_hl_subband_tostring(&value->subband_hl, buff, buff_len);
|
||||
break;
|
||||
default:
|
||||
/* Do nothing */;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srslte_cqi_size(srslte_cqi_value_t *value) {
|
||||
int size = 0;
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
*
|
||||
* \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/.
|
||||
*
|
||||
*/
|
||||
|
||||
// A bunch of helper functions to process device arguments
|
||||
|
||||
|
||||
#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))) {
|
||||
memmove(s,s+strlen(toremove),1+strlen(s+strlen(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';
|
||||
}
|
|
@ -32,21 +32,42 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
#include "rf_soapy_imp.h"
|
||||
#include "srslte/phy/rf/rf.h"
|
||||
#include "rf_helper.h"
|
||||
|
||||
#include <SoapySDR/Device.h>
|
||||
#include <SoapySDR/Formats.h>
|
||||
#include <SoapySDR/Time.h>
|
||||
#include <SoapySDR/Logger.h>
|
||||
#include <Types.h>
|
||||
|
||||
#define USE_TX_MTU 0
|
||||
#define SET_RF_BW 1
|
||||
|
||||
#define PRINT_RX_STATS 0
|
||||
#define PRINT_TX_STATS 0
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
typedef struct {
|
||||
char *devname;
|
||||
SoapySDRKwargs args;
|
||||
SoapySDRDevice *device;
|
||||
SoapySDRRange *ranges;
|
||||
SoapySDRStream *rxStream;
|
||||
SoapySDRStream *txStream;
|
||||
bool tx_stream_active;
|
||||
bool rx_stream_active;
|
||||
srslte_rf_info_t info;
|
||||
char *devname;
|
||||
SoapySDRKwargs args;
|
||||
SoapySDRDevice *device;
|
||||
SoapySDRRange *ranges;
|
||||
SoapySDRStream *rxStream;
|
||||
SoapySDRStream *txStream;
|
||||
bool tx_stream_active;
|
||||
bool rx_stream_active;
|
||||
srslte_rf_info_t info;
|
||||
double tx_rate;
|
||||
size_t rx_mtu, tx_mtu;
|
||||
|
||||
uint32_t num_time_errors;
|
||||
uint32_t num_lates;
|
||||
uint32_t num_overflows;
|
||||
uint32_t num_underflows;
|
||||
uint32_t num_other_errors;
|
||||
uint32_t num_stream_curruption;
|
||||
} rf_soapy_handler_t;
|
||||
|
||||
|
||||
|
@ -61,31 +82,31 @@ int soapy_error(void *h)
|
|||
|
||||
void rf_soapy_get_freq_range(void *h)
|
||||
{
|
||||
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_suppress_handler(const char *x)
|
||||
{
|
||||
// not supported
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_msg_handler(const char *msg)
|
||||
{
|
||||
// not supported
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_suppress_stdout(void *h)
|
||||
{
|
||||
// not supported
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t new_handler)
|
||||
{
|
||||
// not supported
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,14 +130,19 @@ bool rf_soapy_rx_wait_lo_locked(void *h)
|
|||
|
||||
void rf_soapy_set_tx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
{
|
||||
printf("TODO: implement rf_soapy_rx_wait_lo_locked()\n");
|
||||
// not supported
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
double actual_bw = SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_TX, 0);
|
||||
char str_buf[25];
|
||||
snprintf(str_buf, sizeof(str_buf), "%f", actual_bw);
|
||||
if (SoapySDRDevice_writeSetting(handler->device, "CALIBRATE_TX", str_buf)) {
|
||||
printf("Error calibrating Rx\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
{
|
||||
printf("TODO: implement rf_soapy_set_rx_cal()\n");
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
|
@ -202,13 +228,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 = NULL;
|
||||
char* devname = DEVNAME_NONE;
|
||||
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;
|
||||
} else if (!strcmp(soapy_args[i].keys[j],"name") && !strcmp(soapy_args[i].vals[j], "LimeSDR Mini")){
|
||||
devname = DEVNAME_LIME_MINI;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -228,39 +256,46 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
|||
handler->tx_stream_active = false;
|
||||
handler->rx_stream_active = false;
|
||||
handler->devname = devname;
|
||||
if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_RX) > 0){
|
||||
|
||||
// init rx/tx rate to lowest LTE rate to avoid decimation warnings
|
||||
rf_soapy_set_rx_srate(handler, 1.92e6);
|
||||
rf_soapy_set_tx_srate(handler, 1.92e6);
|
||||
|
||||
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) {
|
||||
printf("Rx setupStream fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
handler->rx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->rxStream);
|
||||
}
|
||||
|
||||
if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_TX) > 0){
|
||||
if(SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_TX) > 0){
|
||||
printf("Setting up TX stream\n");
|
||||
if (SoapySDRDevice_setupStream(handler->device, &(handler->txStream), SOAPY_SDR_TX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) {
|
||||
printf("Tx setupStream fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
handler->tx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->txStream);
|
||||
}
|
||||
|
||||
// list device sensors
|
||||
size_t sensor_length;
|
||||
char** sensors;
|
||||
sensors = SoapySDRDevice_listSensors(handler->device, &sensor_length);
|
||||
size_t list_length;
|
||||
char** list;
|
||||
list = SoapySDRDevice_listSensors(handler->device, &list_length);
|
||||
printf("Available device sensors: \n");
|
||||
for(int i = 0; i < sensor_length; i++) {
|
||||
printf(" - %s\n", sensors[i]);
|
||||
for(int i = 0; i < list_length; i++) {
|
||||
printf(" - %s\n", list[i]);
|
||||
}
|
||||
|
||||
// list channel sensors
|
||||
sensors = SoapySDRDevice_listChannelSensors(handler->device, SOAPY_SDR_RX, 0, &sensor_length);
|
||||
list = SoapySDRDevice_listChannelSensors(handler->device, SOAPY_SDR_RX, 0, &list_length);
|
||||
printf("Available sensors for RX channel 0: \n");
|
||||
for(int i = 0; i < sensor_length; i++) {
|
||||
printf(" - %s\n", sensors[i]);
|
||||
for(int i = 0; i < list_length; i++) {
|
||||
printf(" - %s\n", list[i]);
|
||||
}
|
||||
|
||||
/* Set static radio info */
|
||||
// Set static radio info
|
||||
SoapySDRRange tx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_TX, 0);
|
||||
SoapySDRRange rx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_RX, 0);
|
||||
handler->info.min_tx_gain = tx_range.minimum;
|
||||
|
@ -268,6 +303,99 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
|||
handler->info.min_rx_gain = rx_range.minimum;
|
||||
handler->info.max_rx_gain = rx_range.maximum;
|
||||
|
||||
// Check device arguments
|
||||
if (args) {
|
||||
// config file
|
||||
const char config_arg[] = "config=";
|
||||
char config_str[64] = {0};
|
||||
char *config_ptr = strstr(args, config_arg);
|
||||
if (config_ptr) {
|
||||
copy_subdev_string(config_str, config_ptr + strlen(config_arg));
|
||||
printf("Loading config file %s\n", config_str);
|
||||
SoapySDRDevice_writeSetting(handler->device, "LOAD_CONFIG", config_str);
|
||||
remove_substring(args, config_arg);
|
||||
remove_substring(args, config_str);
|
||||
}
|
||||
|
||||
// rx antenna
|
||||
const char rx_ant_arg[] = "rxant=";
|
||||
char rx_ant_str[64] = {0};
|
||||
char *rx_ant_ptr = strstr(args, rx_ant_arg);
|
||||
if (rx_ant_ptr) {
|
||||
copy_subdev_string(rx_ant_str, rx_ant_ptr + strlen(rx_ant_arg));
|
||||
printf("Setting Rx antenna to %s\n", rx_ant_str);
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_RX, 0, rx_ant_str) != 0) {
|
||||
fprintf(stderr, "Failed to set Rx antenna.\n");
|
||||
}
|
||||
remove_substring(args, rx_ant_arg);
|
||||
remove_substring(args, rx_ant_str);
|
||||
}
|
||||
|
||||
// tx antenna
|
||||
const char tx_ant_arg[] = "txant=";
|
||||
char tx_ant_str[64] = {0};
|
||||
char *tx_ant_ptr = strstr(args, tx_ant_arg);
|
||||
if (tx_ant_ptr) {
|
||||
copy_subdev_string(tx_ant_str, tx_ant_ptr + strlen(tx_ant_arg));
|
||||
printf("Setting Tx antenna to %s\n", tx_ant_str);
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_TX, 0, tx_ant_str) != 0) {
|
||||
fprintf(stderr, "Failed to set Tx antenna.\n");
|
||||
}
|
||||
remove_substring(args, tx_ant_arg);
|
||||
remove_substring(args, tx_ant_str);
|
||||
}
|
||||
|
||||
// log level
|
||||
const char loglevel_arg[] = "loglevel=";
|
||||
char loglevel_str[64] = {0};
|
||||
char *loglevel_ptr = strstr(args, loglevel_arg);
|
||||
if (loglevel_ptr) {
|
||||
copy_subdev_string(loglevel_str, loglevel_ptr + strlen(loglevel_arg));
|
||||
if (strcmp(loglevel_str, "error") == 0) {
|
||||
SoapySDR_setLogLevel(SOAPY_SDR_ERROR);
|
||||
}
|
||||
remove_substring(args, loglevel_arg);
|
||||
remove_substring(args, loglevel_str);
|
||||
}
|
||||
}
|
||||
|
||||
// receive one subframe to allow for transceiver calibration
|
||||
if (strstr(devname, "lime")) {
|
||||
// set default tx gain and leave some time to calibrate tx
|
||||
rf_soapy_set_tx_gain(handler, 45);
|
||||
rf_soapy_set_rx_gain(handler, 35);
|
||||
|
||||
cf_t dummy_buffer[1920];
|
||||
cf_t *dummy_buffer_array[SRSLTE_MAX_PORTS];
|
||||
dummy_buffer_array[0] = dummy_buffer;
|
||||
rf_soapy_start_rx_stream(handler, true);
|
||||
rf_soapy_recv_with_time_multi(handler, (void**)dummy_buffer_array, 1920, false, NULL, NULL);
|
||||
rf_soapy_stop_rx_stream(handler);
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
// list gains and AGC mode
|
||||
bool has_agc = SoapySDRDevice_hasGainMode(handler->device, SOAPY_SDR_RX, 0);
|
||||
list = SoapySDRDevice_listGains(handler->device, SOAPY_SDR_RX, 0, &list_length);
|
||||
printf("State of gain elements for Rx channel 0 (AGC %s):\n", has_agc ? "supported":"not supported");
|
||||
for(int i = 0; i < list_length; i++) {
|
||||
printf(" - %s: %.2f dB\n", list[i], SoapySDRDevice_getGainElement(handler->device, SOAPY_SDR_RX, 0, list[i]));
|
||||
}
|
||||
|
||||
has_agc = SoapySDRDevice_hasGainMode(handler->device, SOAPY_SDR_TX, 0);
|
||||
printf("State of gain elements for Tx channel 0 (AGC %s):\n", has_agc ? "supported":"not supported");
|
||||
for(int i = 0; i < list_length; i++) {
|
||||
printf(" - %s: %.2f dB\n", list[i], SoapySDRDevice_getGainElement(handler->device, SOAPY_SDR_TX, 0, list[i]));
|
||||
}
|
||||
|
||||
// print actual antenna configuration
|
||||
char *ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_RX, 0);
|
||||
printf("Rx antenna set to %s\n", ant);
|
||||
|
||||
ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_TX, 0);
|
||||
printf("Tx antenna set to %s\n", ant);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -293,14 +421,25 @@ int rf_soapy_close(void *h)
|
|||
|
||||
SoapySDRDevice_unmake(handler->device);
|
||||
free(handler);
|
||||
|
||||
|
||||
// print statistics
|
||||
if (handler->num_lates) printf("#lates=%d\n", handler->num_lates);
|
||||
if (handler->num_overflows) printf("#overflows=%d\n", handler->num_overflows);
|
||||
if (handler->num_underflows) printf("#underflows=%d\n", handler->num_underflows);
|
||||
if (handler->num_time_errors) printf("#time_errors=%d\n", handler->num_time_errors);
|
||||
if (handler->num_other_errors) printf("#other_errors=%d\n", handler->num_other_errors);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void rf_soapy_set_master_clock_rate(void *h, double rate)
|
||||
{
|
||||
// Allow the soapy to automatically set the appropriate clock rate
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
if (SoapySDRDevice_setMasterClockRate(handler->device, rate) != 0) {
|
||||
printf("rf_soapy_set_master_clock_rate Rx fail: %s\n", SoapySDRDevice_lastError());
|
||||
}
|
||||
|
||||
printf("Set master clock rate to %.2f MHz\n", SoapySDRDevice_getMasterClockRate(handler->device)/1e6);
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,21 +453,75 @@ bool rf_soapy_is_master_clock_dynamic(void *h)
|
|||
double rf_soapy_set_rx_srate(void *h, double rate)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
|
||||
// Restart streaming, as the Lime seems to have problems reconfiguring the sample rate during streaming
|
||||
bool rx_stream_active = handler->rx_stream_active;
|
||||
if (rx_stream_active) {
|
||||
rf_soapy_stop_rx_stream(handler);
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_RX, 0, rate) != 0) {
|
||||
printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
#if SET_RF_BW
|
||||
// Set bandwidth close to current rate
|
||||
size_t bw_length;
|
||||
SoapySDRRange *bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_RX, 0, &bw_length);
|
||||
double bw = rate * 0.75;
|
||||
bw = MIN(bw, bw_range->maximum);
|
||||
bw = MAX(bw, bw_range->minimum);
|
||||
bw = MAX(bw, 2.5e6); // For the Lime to avoid warnings
|
||||
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, 0, bw) != 0) {
|
||||
printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
printf("Set Rx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_RX, 0)/1e6);
|
||||
#endif
|
||||
|
||||
if (rx_stream_active) {
|
||||
rf_soapy_start_rx_stream(handler, true);
|
||||
}
|
||||
|
||||
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0);
|
||||
}
|
||||
|
||||
double rf_soapy_set_tx_srate(void *h, double rate)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
|
||||
// stop/start streaming during rate reconfiguration
|
||||
bool rx_stream_active = handler->rx_stream_active;
|
||||
if (handler->rx_stream_active) {
|
||||
rf_soapy_stop_rx_stream(handler);
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_TX, 0, rate) != 0) {
|
||||
printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0);
|
||||
|
||||
#if SET_RF_BW
|
||||
size_t bw_length;
|
||||
SoapySDRRange *bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_TX, 0, &bw_length);
|
||||
// try to set the BW a bit narrower than sampling rate to prevent aliasing but make sure to stay within device boundaries
|
||||
double bw = rate * 0.75;
|
||||
bw = MAX(bw, bw_range->minimum);
|
||||
bw = MIN(bw, bw_range->maximum);
|
||||
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, bw) != 0) {
|
||||
printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
printf("Set Tx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_TX, 0)/1e6);
|
||||
#endif
|
||||
|
||||
if (rx_stream_active) {
|
||||
rf_soapy_start_rx_stream(handler, true);
|
||||
}
|
||||
|
||||
handler->tx_rate = SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX, 0);
|
||||
return handler->tx_rate;
|
||||
}
|
||||
|
||||
|
||||
|
@ -359,14 +552,14 @@ double rf_soapy_set_tx_gain(void *h, double gain)
|
|||
double rf_soapy_get_rx_gain(void *h)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
return SoapySDRDevice_getGain(handler->device,SOAPY_SDR_RX,0);
|
||||
return SoapySDRDevice_getGain(handler->device, SOAPY_SDR_RX, 0);
|
||||
}
|
||||
|
||||
|
||||
double rf_soapy_get_tx_gain(void *h)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
return SoapySDRDevice_getGain(handler->device,SOAPY_SDR_TX,0);
|
||||
return SoapySDRDevice_getGain(handler->device, SOAPY_SDR_TX, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -389,14 +582,10 @@ double rf_soapy_set_rx_freq(void *h, double freq)
|
|||
printf("setFrequency fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
printf("Tuned Rx to %.2f MHz\n", SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0)/1e6);
|
||||
|
||||
// Todo: expose antenna setting
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_RX, 0, "LNAH") != 0) {
|
||||
fprintf(stderr, "Failed to set Rx antenna.\n");
|
||||
}
|
||||
|
||||
char *ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_RX, 0);
|
||||
printf("Rx antenna set to %s\n", ant);
|
||||
// wait until LO is locked
|
||||
rf_soapy_rx_wait_lo_locked(handler);
|
||||
|
||||
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0);
|
||||
}
|
||||
|
@ -410,13 +599,7 @@ double rf_soapy_set_tx_freq(void *h, double freq)
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Todo: expose antenna name in arguments
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_TX, 0, "BAND1") != 0) {
|
||||
fprintf(stderr, "Failed to set Tx antenna.\n");
|
||||
}
|
||||
|
||||
char *ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_TX, 0);
|
||||
printf("Tx antenna set to %s\n", ant);
|
||||
printf("Tuned Tx to %.2f MHz\n", SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0)/1e6);
|
||||
|
||||
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0);
|
||||
}
|
||||
|
@ -439,42 +622,59 @@ int rf_soapy_recv_with_time_multi(void *h,
|
|||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
int flags; //flags set by receive operation
|
||||
int num_channels = 1; // temp
|
||||
const long timeoutUs = 1000000; // arbitrarily chosen
|
||||
const long timeoutUs = 400000; // arbitrarily chosen
|
||||
|
||||
int trials = 0;
|
||||
int ret = 0;
|
||||
long long timeNs; //timestamp for receive buffer
|
||||
int n = 0;
|
||||
|
||||
#if PRINT_RX_STATS
|
||||
printf("rx: nsamples=%d rx_mtu=%zd\n", nsamples, handler->rx_mtu);
|
||||
#endif
|
||||
|
||||
do {
|
||||
size_t rx_samples = nsamples;
|
||||
|
||||
if (rx_samples > nsamples - n){
|
||||
rx_samples = nsamples - n;
|
||||
}
|
||||
size_t rx_samples = MIN(nsamples - n, handler->rx_mtu);
|
||||
#if PRINT_RX_STATS
|
||||
printf(" - rx_samples=%zd\n", rx_samples);
|
||||
#endif
|
||||
|
||||
void *buffs_ptr[4];
|
||||
for (int i=0; i<num_channels; i++){
|
||||
cf_t *data_c = (cf_t*) data[i];
|
||||
buffs_ptr[i] = &data_c[n];
|
||||
}
|
||||
|
||||
ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr, rx_samples, &flags, &timeNs, timeoutUs);
|
||||
if(ret < 0) {
|
||||
// continue when getting overflows
|
||||
if (ret == SOAPY_SDR_OVERFLOW) {
|
||||
fprintf(stderr, "O");
|
||||
fflush(stderr);
|
||||
continue;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (ret == SOAPY_SDR_OVERFLOW || (ret > 0 && (flags & SOAPY_SDR_END_ABRUPT) != 0)) {
|
||||
handler->num_overflows++;
|
||||
fprintf(stderr, "O");
|
||||
fflush(stderr);
|
||||
continue;
|
||||
} else
|
||||
if (ret == SOAPY_SDR_TIMEOUT) {
|
||||
handler->num_time_errors++;
|
||||
fprintf(stderr, "T");
|
||||
fflush(stderr);
|
||||
continue;
|
||||
} else
|
||||
if (ret < 0) {
|
||||
// unspecific error
|
||||
printf("SoapySDRDevice_readStream returned %d: %s\n", ret, SoapySDR_errToStr(ret));
|
||||
handler->num_other_errors++;
|
||||
}
|
||||
|
||||
// update rx time
|
||||
if (secs != NULL && frac_secs != NULL) {
|
||||
// update rx time only for first segment
|
||||
if (secs != NULL && frac_secs != NULL && n == 0) {
|
||||
*secs = timeNs / 1e9;
|
||||
*frac_secs = (timeNs % 1000000000)/1e9;
|
||||
//printf("rx_time: secs=%d, frac_secs=%lf timeNs=%lld\n", *secs, *frac_secs, timeNs);
|
||||
//printf("rx_time: secs=%lld, frac_secs=%lf timeNs=%llu\n", *secs, *frac_secs, timeNs);
|
||||
}
|
||||
|
||||
#if PRINT_RX_STATS
|
||||
printf(" - rx: %d/%zd\n", ret, rx_samples);
|
||||
#endif
|
||||
|
||||
n += ret;
|
||||
trials++;
|
||||
} while (n < nsamples && trials < 100);
|
||||
|
@ -522,65 +722,103 @@ int rf_soapy_send_timed_multi(void *h,
|
|||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t *) h;
|
||||
int flags = 0;
|
||||
const long timeoutUs = 2000; // arbitrarily chosen
|
||||
const long timeoutUs = 100000; // arbitrarily chosen
|
||||
long long timeNs = 0;
|
||||
int trials = 0;
|
||||
int ret = 0;
|
||||
int n = 0;
|
||||
|
||||
#if PRINT_TX_STATS
|
||||
printf("tx: namples=%d, mtu=%zd\n", nsamples, handler->tx_mtu);
|
||||
#endif
|
||||
|
||||
if (!handler->tx_stream_active) {
|
||||
rf_soapy_start_tx_stream(h);
|
||||
}
|
||||
|
||||
if (is_start_of_burst && is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_ONE_PACKET;
|
||||
}
|
||||
|
||||
if (is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_END_BURST;
|
||||
}
|
||||
|
||||
// Convert initial tx time
|
||||
if (has_time_spec) {
|
||||
flags |= SOAPY_SDR_HAS_TIME;
|
||||
timeNs = secs * 1000000000;
|
||||
timeNs = timeNs + (frac_secs * 1000000000);
|
||||
//printf("time_spec: secs=%d, frac_secs=%lf timeNs=%lld\n", secs, frac_secs, timeNs);
|
||||
}
|
||||
|
||||
do {
|
||||
#if USE_TX_MTU
|
||||
size_t tx_samples = MIN(nsamples - n, handler->tx_mtu);
|
||||
#else
|
||||
size_t tx_samples = nsamples;
|
||||
if (tx_samples > nsamples - n) {
|
||||
tx_samples = nsamples - n;
|
||||
}
|
||||
#endif
|
||||
|
||||
// (re-)set stream flags
|
||||
flags = 0;
|
||||
if (is_start_of_burst && is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_ONE_PACKET;
|
||||
}
|
||||
|
||||
if (is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_END_BURST;
|
||||
}
|
||||
|
||||
// only set time flag for first tx
|
||||
if(has_time_spec && n == 0) {
|
||||
flags |= SOAPY_SDR_HAS_TIME;
|
||||
}
|
||||
|
||||
#if PRINT_TX_STATS
|
||||
printf(" - tx_samples=%zd at timeNs=%llu flags=%d\n", tx_samples, timeNs, flags);
|
||||
#endif
|
||||
|
||||
ret = SoapySDRDevice_writeStream(handler->device, handler->txStream, (const void *)data, tx_samples, &flags, timeNs, timeoutUs);
|
||||
if (ret == SOAPY_SDR_TIMEOUT) {
|
||||
printf("L");
|
||||
continue;
|
||||
}
|
||||
if (ret == SOAPY_SDR_OVERFLOW) {
|
||||
printf("O");
|
||||
continue;
|
||||
}
|
||||
if (ret == SOAPY_SDR_UNDERFLOW) {
|
||||
printf("U");
|
||||
continue;
|
||||
if (ret >= 0) {
|
||||
// Tx was ok
|
||||
#if PRINT_TX_STATS
|
||||
printf(" - tx: %d/%zd\n", ret, tx_samples);
|
||||
#endif
|
||||
// Advance tx time
|
||||
if (has_time_spec && ret < nsamples) {
|
||||
long long adv = SoapySDR_ticksToTimeNs(ret, handler->tx_rate);
|
||||
#if PRINT_TX_STATS
|
||||
printf(" - tx: timeNs_old=%llu, adv=%llu, timeNs_new=%llu, tx_rate=%f\n", timeNs, adv, timeNs+adv, handler->tx_rate);
|
||||
#endif
|
||||
timeNs += adv;
|
||||
}
|
||||
n += ret;
|
||||
}
|
||||
else
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error during writeStream\n");
|
||||
exit(-1);
|
||||
return SRSLTE_ERROR;
|
||||
// An error has occured
|
||||
switch (ret) {
|
||||
case SOAPY_SDR_TIMEOUT:
|
||||
handler->num_lates++;
|
||||
printf("L");
|
||||
break;
|
||||
case SOAPY_SDR_STREAM_ERROR:
|
||||
handler->num_stream_curruption++;
|
||||
printf("E");
|
||||
break;
|
||||
case SOAPY_SDR_TIME_ERROR:
|
||||
handler->num_time_errors++;
|
||||
printf("T");
|
||||
break;
|
||||
case SOAPY_SDR_UNDERFLOW:
|
||||
handler->num_underflows++;
|
||||
printf("U");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error during writeStream\n");
|
||||
exit(-1);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
n += ret;
|
||||
trials++;
|
||||
} while (n < nsamples && trials < 100);
|
||||
|
||||
if (n != nsamples) {
|
||||
fprintf(stderr, "Couldn't write all samples.\n");
|
||||
return SRSLTE_ERROR;
|
||||
fprintf(stderr, "Couldn't write all samples after %d trials.\n", trials);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#include <stdint.h>
|
||||
#include "srslte/config.h"
|
||||
#include "srslte/phy/rf/rf.h"
|
||||
#define DEVNAME_NONE "none"
|
||||
#define DEVNAME_LIME "lime"
|
||||
#define DEVNAME_LIME_MINI "lime_mini"
|
||||
|
||||
SRSLTE_API int rf_soapy_open(char *args,
|
||||
void **handler);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
#include "rf_uhd_imp.h"
|
||||
#include "srslte/phy/rf/rf.h"
|
||||
#include "rf_helper.h"
|
||||
#include "uhd_c_api.h"
|
||||
|
||||
#define HAVE_ASYNC_THREAD 1
|
||||
|
@ -320,31 +320,6 @@ 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))) {
|
||||
memmove(s,s+strlen(toremove),1+strlen(s+strlen(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) {
|
||||
|
@ -807,7 +782,7 @@ int rf_uhd_recv_with_time_multi(void *h,
|
|||
|
||||
rxd_samples = 0;
|
||||
uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr,
|
||||
num_rx_samples, md, 1.0, false, &rxd_samples);
|
||||
num_rx_samples, md, 0.1, false, &rxd_samples);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error receiving from UHD: %d\n", error);
|
||||
log_rx_error(handler);
|
||||
|
@ -917,7 +892,7 @@ int rf_uhd_send_timed_multi(void *h,
|
|||
buffs_ptr[i] = buff;
|
||||
}
|
||||
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr,
|
||||
tx_samples, &handler->tx_md, 3.0, &txd_samples);
|
||||
tx_samples, &handler->tx_md, 0.1, &txd_samples);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error sending to UHD: %d\n", error);
|
||||
goto unlock;
|
||||
|
@ -939,7 +914,7 @@ int rf_uhd_send_timed_multi(void *h,
|
|||
uhd_tx_metadata_set_has_time_spec(&handler->tx_md, is_start_of_burst);
|
||||
uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst);
|
||||
uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst);
|
||||
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 3.0, &txd_samples);
|
||||
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 0.0, &txd_samples);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error sending to UHD: %d\n", error);
|
||||
goto unlock;
|
||||
|
|
|
@ -491,6 +491,9 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
|
|||
int found_dci = srslte_ue_dl_find_dl_dci(q, tm, cfi, sf_idx, rnti, &dci_msg);
|
||||
if (found_dci == 1) {
|
||||
|
||||
INFO("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti=%d\n", srslte_dci_format_string(dci_msg.format),
|
||||
q->current_rnti, q->last_location.ncce, (1<<q->last_location.L), tti);
|
||||
|
||||
if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, q->cell.nof_ports, &dci_unpacked, &grant)) {
|
||||
fprintf(stderr, "Error unpacking DCI\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
|
|
@ -23,3 +23,5 @@ if(RF_FOUND)
|
|||
target_link_libraries(srslte_radio srslte_rf)
|
||||
install(TARGETS srslte_radio DESTINATION ${LIBRARY_DIR})
|
||||
endif(RF_FOUND)
|
||||
|
||||
add_subdirectory(test)
|
|
@ -59,7 +59,7 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels)
|
|||
} else if (strstr(srslte_rf_name(&rf_device), "bladerf")) {
|
||||
burst_preamble_sec = blade_default_burst_preamble_sec;
|
||||
} else {
|
||||
burst_preamble_sec = 0;
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,9 @@ bool radio::is_init() {
|
|||
|
||||
void radio::stop()
|
||||
{
|
||||
srslte_rf_close(&rf_device);
|
||||
if (is_initialized) {
|
||||
srslte_rf_close(&rf_device);
|
||||
}
|
||||
}
|
||||
|
||||
void radio::reset()
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# Copyright 2013-2017 Software Radio Systems Limited
|
||||
#
|
||||
# This file is part of srsLTE
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
if(RF_FOUND)
|
||||
add_executable(benchmark_radio benchmark_radio.cc)
|
||||
target_link_libraries(benchmark_radio srslte_radio)
|
||||
endif(RF_FOUND)
|
||||
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
*
|
||||
* \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/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/radio/radio_multi.h"
|
||||
|
||||
using namespace srslte;
|
||||
|
||||
std::string device_args = "auto";
|
||||
|
||||
double freq = 2630e6;
|
||||
uint32_t nof_ports = 1;
|
||||
double srate = 1.92e6; /* Hz */
|
||||
double duration = 0.01; /* in seconds, 10 ms by default */
|
||||
cf_t *buffers[SRSLTE_MAX_PORTS];
|
||||
bool tx_enable = false;
|
||||
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [rpstvh]\n", prog);
|
||||
printf("\t-f Carrier frequency in Hz [Default %f]\n", freq);
|
||||
printf("\t-a Arguments for first radio [Default %s]\n", device_args.c_str());
|
||||
printf("\t-p number of ports 1-%d [Default %d]\n", SRSLTE_MAX_PORTS, nof_ports);
|
||||
printf("\t-s sampling rate [Default %.0f]\n", srate);
|
||||
printf("\t-t duration in seconds [Default %.3f]\n", duration);
|
||||
printf("\t-x enable transmit [Default %s]\n", (tx_enable) ? "enabled" : "disabled");
|
||||
printf("\t-v Set srslte_verbose to info (v) or debug (vv) [Default none]\n");
|
||||
printf("\t-h show this message\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "foabcderpstvhmxw")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
freq = atof(argv[optind]);
|
||||
break;
|
||||
case 'a':
|
||||
device_args = std::string(argv[optind]);
|
||||
break;
|
||||
case 'p':
|
||||
nof_ports = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 's':
|
||||
srate = atof(argv[optind]);
|
||||
break;
|
||||
case 't':
|
||||
duration = atof(argv[optind]);
|
||||
break;
|
||||
case 'x':
|
||||
tx_enable ^= true;
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
srslte::radio_multi *radio_h = NULL;
|
||||
srslte_timestamp_t ts_rx = {}, ts_tx = {};
|
||||
|
||||
/* Parse args */
|
||||
parse_args(argc, argv);
|
||||
|
||||
uint32_t nof_samples = (uint32_t) (duration * srate);
|
||||
uint32_t frame_size = (uint32_t) (srate / 1000.0); /* 1 ms at srate */
|
||||
uint32_t nof_frames = (uint32_t) ceil(nof_samples / frame_size);
|
||||
|
||||
radio_h = new radio_multi();
|
||||
if (!radio_h) {
|
||||
fprintf(stderr, "Error: Calling radio_multi constructor\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
for (uint32_t p = 0; p < SRSLTE_MAX_PORTS; p++) {
|
||||
buffers[p] = NULL;
|
||||
}
|
||||
|
||||
for (uint32_t p = 0; p < nof_ports; p++) {
|
||||
buffers[p] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * frame_size);
|
||||
if (!buffers[p]) {
|
||||
fprintf(stderr, "Error: Allocating buffer (%d)\n", p);
|
||||
goto clean_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise instances */
|
||||
printf("Initialising instances...\n");
|
||||
if (!radio_h->init((char*)device_args.c_str(), NULL, nof_ports)) {
|
||||
fprintf(stderr, "Error: Calling radio_multi constructor\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
radio_h->set_rx_freq(freq);
|
||||
|
||||
/* Set radio */
|
||||
printf("Setting radio...\n");
|
||||
if (srate < 10e6) {
|
||||
radio_h->set_master_clock_rate(4 * srate);
|
||||
} else {
|
||||
radio_h->set_master_clock_rate(srate);
|
||||
}
|
||||
|
||||
radio_h->set_rx_srate(srate);
|
||||
if (tx_enable) {
|
||||
radio_h->set_tx_srate(srate);
|
||||
}
|
||||
|
||||
/* Receive */
|
||||
printf("Initial receive for aligning radios...\n");
|
||||
radio_h->rx_now(buffers, frame_size, &ts_rx);
|
||||
|
||||
printf("Start capturing %d frames of %d samples...\n", nof_frames, frame_size);
|
||||
|
||||
for (uint32_t i = 0; i < nof_frames; i++) {
|
||||
frame_size = SRSLTE_MIN(frame_size, nof_samples);
|
||||
radio_h->rx_now(buffers, frame_size, &ts_rx);
|
||||
|
||||
if (tx_enable) {
|
||||
srslte_timestamp_copy(&ts_tx, &ts_rx);
|
||||
srslte_timestamp_add(&ts_tx, 0, 0.004);
|
||||
radio_h->tx_single(buffers[0], frame_size, ts_tx);
|
||||
}
|
||||
|
||||
nof_samples -= frame_size;
|
||||
}
|
||||
|
||||
printf("Finished streaming ...\n");
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
clean_exit:
|
||||
printf("Tearing down...\n");
|
||||
|
||||
radio_h->stop();
|
||||
|
||||
for (uint32_t p = 0; p < nof_ports; p++) {
|
||||
if (buffers[p]) {
|
||||
free(buffers[p]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
printf("Failed!\n");
|
||||
} else {
|
||||
printf("Ok!\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -277,7 +277,7 @@ uint32_t rlc_am::get_buffer_state()
|
|||
// check if pollRetx timer expired (Section 5.2.2.3 in TS 36.322)
|
||||
if (poll_retx()) {
|
||||
// if both tx and retx buffer are empty, retransmit next PDU to be ack'ed
|
||||
log->info("Poll reTx timer expired (lcid=%d)\n", lcid);
|
||||
log->debug("Poll reTx timer expired (lcid=%d)\n", lcid);
|
||||
if ((tx_window.size() > 0 && retx_queue.size() == 0 && tx_sdu_queue.size() == 0)) {
|
||||
std::map<uint32_t, rlc_amd_tx_pdu_t>::iterator it = tx_window.find(vt_s - 1);
|
||||
if (it != tx_window.end()) {
|
||||
|
|
|
@ -71,7 +71,7 @@ class gtpu
|
|||
{
|
||||
public:
|
||||
|
||||
bool init(std::string gtp_bind_addr_, std::string mme_addr_, pdcp_interface_gtpu *pdcp_, srslte::log *gtpu_log_);
|
||||
bool init(std::string gtp_bind_addr_, std::string mme_addr_, pdcp_interface_gtpu *pdcp_, srslte::log *gtpu_log_, bool enable_mbsfn = false);
|
||||
void stop();
|
||||
|
||||
// gtpu_interface_rrc
|
||||
|
@ -90,9 +90,9 @@ private:
|
|||
bool running;
|
||||
bool run_enable;
|
||||
|
||||
bool mch_running;
|
||||
bool mch_running;
|
||||
bool mch_run_enable;
|
||||
|
||||
bool _enable_mbsfn;
|
||||
std::string gtp_bind_addr;
|
||||
std::string mme_addr;
|
||||
srsenb::pdcp_interface_gtpu *pdcp;
|
||||
|
|
|
@ -251,6 +251,8 @@ public:
|
|||
|
||||
struct timeval t_last_activity;
|
||||
|
||||
LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establishment_cause;
|
||||
|
||||
// S-TMSI for this UE
|
||||
bool has_tmsi;
|
||||
uint32_t m_tmsi;
|
||||
|
|
|
@ -72,8 +72,8 @@ public:
|
|||
void run_thread();
|
||||
|
||||
// RRC interface
|
||||
void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu);
|
||||
void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec);
|
||||
void initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu);
|
||||
void initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec);
|
||||
void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu);
|
||||
bool user_exists(uint16_t rnti);
|
||||
bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio);
|
||||
|
@ -128,7 +128,7 @@ private:
|
|||
bool handle_s1setupfailure(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT *msg);
|
||||
bool handle_erabsetuprequest(LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT *msg);
|
||||
|
||||
bool send_initialuemessage(uint16_t rnti, srslte::byte_buffer_t *pdu, bool has_tmsi, uint32_t m_tmsi=0, uint8_t mmec=0);
|
||||
bool send_initialuemessage(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu, bool has_tmsi, uint32_t m_tmsi=0, uint8_t mmec=0);
|
||||
bool send_ulnastransport(uint16_t rnti, srslte::byte_buffer_t *pdu);
|
||||
bool send_uectxtreleaserequest(uint16_t rnti, LIBLTE_S1AP_CAUSE_STRUCT *cause);
|
||||
bool send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_t enb_ue_id);
|
||||
|
|
|
@ -219,7 +219,7 @@ bool enb::init(all_args_t *args_)
|
|||
pdcp.init(&rlc, &rrc, >pu, &pdcp_log);
|
||||
rrc.init(&rrc_cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_log);
|
||||
s1ap.init(args->enb.s1ap, &rrc, &s1ap_log);
|
||||
gtpu.init(args->enb.s1ap.gtp_bind_addr, args->enb.s1ap.mme_addr, &pdcp, >pu_log);
|
||||
gtpu.init(args->enb.s1ap.gtp_bind_addr, args->enb.s1ap.mme_addr, &pdcp, >pu_log, args->expert.enable_mbsfn);
|
||||
|
||||
started = true;
|
||||
return true;
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
using namespace std;
|
||||
|
||||
// Enable this to log SI
|
||||
//#define LOG_THIS(a) 1
|
||||
#define LOG_THIS(a) 1
|
||||
|
||||
// Enable this one to skip SI-RNTI
|
||||
#define LOG_THIS(rnti) (rnti != 0xFFFF)
|
||||
//#define LOG_THIS(rnti) (rnti != 0xFFFF)
|
||||
|
||||
|
||||
/* Define GUI-related things */
|
||||
|
|
|
@ -34,7 +34,7 @@ using namespace srslte;
|
|||
|
||||
namespace srsenb {
|
||||
|
||||
bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_interface_gtpu* pdcp_, srslte::log* gtpu_log_)
|
||||
bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_interface_gtpu* pdcp_, srslte::log* gtpu_log_, bool enable_mbsfn)
|
||||
{
|
||||
pdcp = pdcp_;
|
||||
gtpu_log = gtpu_log_;
|
||||
|
@ -95,11 +95,13 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_
|
|||
//Setup M1-u
|
||||
init_m1u(gtpu_log_);
|
||||
|
||||
mch_lcid_counter = 1;
|
||||
_enable_mbsfn = enable_mbsfn;
|
||||
// Setup a thread to receive packets from the src socket
|
||||
start(THREAD_PRIO);
|
||||
pthread_create(&mch_thread ,NULL ,mch_thread_routine , this);
|
||||
|
||||
if(_enable_mbsfn){
|
||||
mch_lcid_counter = 1;
|
||||
pthread_create(&mch_thread ,NULL ,mch_thread_routine , this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -224,8 +226,9 @@ void gtpu::stop()
|
|||
}
|
||||
}
|
||||
wait_thread_finish();
|
||||
pthread_join(mch_thread, NULL);
|
||||
|
||||
if(_enable_mbsfn) {
|
||||
pthread_join(mch_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (snk_fd) {
|
||||
|
|
|
@ -1043,6 +1043,7 @@ void rrc::ue::handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg)
|
|||
m_tmsi = msg->ue_id.s_tmsi.m_tmsi;
|
||||
has_tmsi = true;
|
||||
}
|
||||
establishment_cause = msg->cause;
|
||||
send_connection_setup();
|
||||
state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE;
|
||||
}
|
||||
|
@ -1069,9 +1070,9 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE
|
|||
parent->mac->phy_config_enabled(rnti, true);
|
||||
|
||||
if(has_tmsi) {
|
||||
parent->s1ap->initial_ue(rnti, pdu, m_tmsi, mmec);
|
||||
parent->s1ap->initial_ue(rnti, (LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM)establishment_cause, pdu, m_tmsi, mmec);
|
||||
} else {
|
||||
parent->s1ap->initial_ue(rnti, pdu);
|
||||
parent->s1ap->initial_ue(rnti, (LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM)establishment_cause, pdu);
|
||||
}
|
||||
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
|
||||
}
|
||||
|
|
|
@ -174,22 +174,22 @@ void s1ap::build_tai_cgi()
|
|||
/*******************************************************************************
|
||||
/* RRC interface
|
||||
********************************************************************************/
|
||||
void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu)
|
||||
void s1ap::initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu)
|
||||
{
|
||||
ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++;
|
||||
ue_ctxt_map[rnti].stream_id = 1;
|
||||
ue_ctxt_map[rnti].release_requested = false;
|
||||
enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti;
|
||||
send_initialuemessage(rnti, pdu, false);
|
||||
send_initialuemessage(rnti, cause, pdu, false);
|
||||
}
|
||||
|
||||
void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec)
|
||||
void s1ap::initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec)
|
||||
{
|
||||
ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++;
|
||||
ue_ctxt_map[rnti].stream_id = 1;
|
||||
ue_ctxt_map[rnti].release_requested = false;
|
||||
enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti;
|
||||
send_initialuemessage(rnti, pdu, true, m_tmsi, mmec);
|
||||
send_initialuemessage(rnti, cause, pdu, true, m_tmsi, mmec);
|
||||
}
|
||||
|
||||
void s1ap::write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu)
|
||||
|
@ -609,7 +609,7 @@ bool s1ap::handle_s1setupfailure(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT *msg)
|
|||
/* S1AP message senders
|
||||
********************************************************************************/
|
||||
|
||||
bool s1ap::send_initialuemessage(uint16_t rnti, srslte::byte_buffer_t *pdu, bool has_tmsi, uint32_t m_tmsi, uint8_t mmec)
|
||||
bool s1ap::send_initialuemessage(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::byte_buffer_t *pdu, bool has_tmsi, uint32_t m_tmsi, uint8_t mmec)
|
||||
{
|
||||
if(!mme_connected) {
|
||||
return false;
|
||||
|
@ -662,7 +662,7 @@ bool s1ap::send_initialuemessage(uint16_t rnti, srslte::byte_buffer_t *pdu, bool
|
|||
|
||||
// RRC Establishment Cause
|
||||
initue->RRC_Establishment_Cause.ext = false;
|
||||
initue->RRC_Establishment_Cause.e = LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_MO_SIGNALLING;
|
||||
initue->RRC_Establishment_Cause.e = cause;
|
||||
|
||||
liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg);
|
||||
s1ap_log->info_hex(msg.msg, msg.N_bytes, "Sending InitialUEMessage for RNTI:0x%x", rnti);
|
||||
|
@ -939,7 +939,7 @@ bool s1ap::send_initial_ctxt_setup_failure(uint16_t rnti)
|
|||
fail->Cause.choice.radioNetwork.ext = false;
|
||||
fail->Cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_UNSPECIFIED;
|
||||
|
||||
liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)&buf);
|
||||
liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)buf);
|
||||
s1ap_log->info_hex(buf->msg, buf->N_bytes, "Sending InitialContextSetupFailure for RNTI:0x%x", rnti);
|
||||
|
||||
ssize_t n_sent = sctp_sendmsg(socket_fd, buf->msg, buf->N_bytes,
|
||||
|
|
|
@ -78,31 +78,19 @@ public:
|
|||
uint32_t get_next_mme_ue_s1ap_id();
|
||||
enb_ctx_t* find_enb_ctx(uint16_t enb_id);
|
||||
void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri);
|
||||
void get_enb_ctx(uint16_t sctp_stream);
|
||||
|
||||
bool add_ue_ctx_to_imsi_map(ue_ctx_t *ue_ctx);
|
||||
bool add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx_t *ue_ctx);
|
||||
bool add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id);
|
||||
|
||||
ue_ctx_t* find_ue_ctx_from_imsi(uint64_t imsi);
|
||||
ue_ctx_t* find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id);
|
||||
|
||||
bool release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id);
|
||||
void release_ues_ecm_ctx_in_enb(uint16_t enb_id);
|
||||
void release_ues_ecm_ctx_in_enb(int32_t enb_assoc);
|
||||
bool delete_ue_ctx(uint64_t imsi);
|
||||
|
||||
//ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id);
|
||||
//void add_new_ue_ctx(const ue_ctx_t &ue_ctx);
|
||||
|
||||
//void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx);
|
||||
//void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx);
|
||||
//ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi);
|
||||
//ue_ecm_ctx_t* find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id);
|
||||
//bool delete_ue_emm_ctx(uint64_t imsi);
|
||||
//bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id);
|
||||
//void delete_ues_ecm_ctx_in_enb(uint16_t enb_id);
|
||||
|
||||
//void store_tmp_ue_emm_ctx(const ue_emm_ctx_t &ue_ecm_ctx);
|
||||
//bool get_tmp_ue_emm_ctx(uint32_t mme_ue_s1ap_id, ue_emm_ctx_t* ue_emm_ptr);
|
||||
|
||||
uint32_t allocate_m_tmsi(uint64_t imsi);
|
||||
|
||||
s1ap_args_t m_s1ap_args;
|
||||
|
@ -127,16 +115,11 @@ private:
|
|||
int m_s1mme;
|
||||
std::map<uint16_t, enb_ctx_t*> m_active_enbs;
|
||||
std::map<int32_t, uint16_t> m_sctp_to_enb_id;
|
||||
std::map<uint16_t,std::set<uint32_t> > m_enb_id_to_ue_ids;
|
||||
|
||||
std::map<int32_t,std::set<uint32_t> > m_enb_assoc_to_ue_ids;
|
||||
|
||||
std::map<uint64_t, ue_ctx_t*> m_imsi_to_ue_ctx;
|
||||
std::map<uint32_t, ue_ctx_t*> m_mme_ue_s1ap_id_to_ue_ctx;
|
||||
|
||||
//std::map<uint64_t, ue_emm_ctx_t*> m_imsi_to_ue_emm_ctx;
|
||||
//std::map<uint32_t, ue_ecm_ctx_t*> m_mme_ue_s1ap_id_to_ue_ecm_ctx;
|
||||
//std::map<int32_t,ue_emm_ctx_t*> m_mme_ue_s1ap_id_to_tmp_ue_emm_ctx;
|
||||
|
||||
uint32_t m_next_mme_ue_s1ap_id;
|
||||
uint32_t m_next_m_tmsi;
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn
|
|||
return false;
|
||||
}
|
||||
gen_rand(rand);
|
||||
|
||||
|
||||
security_milenage_f2345( k,
|
||||
opc,
|
||||
rand,
|
||||
|
@ -534,7 +534,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|||
mcc,
|
||||
mnc,
|
||||
k_asme);
|
||||
|
||||
|
||||
m_hss_log->debug("User MCC : %x MNC : %x \n", mcc, mnc);
|
||||
m_hss_log->debug_hex(k_asme, 32, "User k_asme : ");
|
||||
|
||||
|
@ -668,7 +668,7 @@ bool hss::get_ue_ctx(uint64_t imsi, hss_ue_ctx_t **ue_ctx)
|
|||
m_hss_log->info("User not found. IMSI: %015lu\n",imsi);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
*ue_ctx = ue_ctx_it->second;
|
||||
return true;
|
||||
}
|
||||
|
@ -701,6 +701,7 @@ hss::get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint le
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
hss::hex_string(uint8_t *hex, int size)
|
||||
{
|
||||
|
@ -712,4 +713,15 @@ hss::hex_string(uint8_t *hex, int size)
|
|||
}
|
||||
return ss.str();
|
||||
}
|
||||
/*
|
||||
uint64_t
|
||||
string_to_imsi()
|
||||
{
|
||||
uint64_t imsi = 0;
|
||||
for(int i=0;i<=14;i++){
|
||||
imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i);
|
||||
}
|
||||
return imsi;
|
||||
}
|
||||
*/
|
||||
} //namespace srsepc
|
||||
|
|
|
@ -299,7 +299,7 @@ s1ap::add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *en
|
|||
memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx_t));
|
||||
m_active_enbs.insert(std::pair<uint16_t,enb_ctx_t*>(enb_ptr->enb_id,enb_ptr));
|
||||
m_sctp_to_enb_id.insert(std::pair<int32_t,uint16_t>(enb_sri->sinfo_assoc_id, enb_ptr->enb_id));
|
||||
m_enb_id_to_ue_ids.insert(std::pair<uint16_t,std::set<uint32_t> >(enb_ptr->enb_id,ue_set));
|
||||
m_enb_assoc_to_ue_ids.insert(std::pair<int32_t,std::set<uint32_t> >(enb_sri->sinfo_assoc_id,ue_set));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ s1ap::delete_enb_ctx(int32_t assoc_id)
|
|||
m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id);
|
||||
|
||||
//Delete connected UEs ctx
|
||||
release_ues_ecm_ctx_in_enb(enb_id);
|
||||
release_ues_ecm_ctx_in_enb(assoc_id);
|
||||
|
||||
//Delete eNB
|
||||
delete it_ctx->second;
|
||||
|
@ -397,6 +397,27 @@ s1ap::add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx_t *ue_ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
s1ap::add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id)
|
||||
{
|
||||
|
||||
std::map<int32_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc);
|
||||
if(ues_in_enb == m_enb_assoc_to_ue_ids.end())
|
||||
{
|
||||
m_s1ap_log->error("Could not find eNB from eNB SCTP association %d",enb_assoc);
|
||||
return false;
|
||||
}
|
||||
std::set<uint32_t>::iterator ue_id = ues_in_enb->second.find(mme_ue_s1ap_id);
|
||||
if(ue_id != ues_in_enb->second.end())
|
||||
{
|
||||
m_s1ap_log->error("UE with MME UE S1AP Id already exists %d",mme_ue_s1ap_id);
|
||||
return false;
|
||||
}
|
||||
ues_in_enb->second.insert(mme_ue_s1ap_id);
|
||||
m_s1ap_log->debug("Added UE with MME-UE S1AP Id %d to eNB with association %d\n", mme_ue_s1ap_id, enb_assoc);
|
||||
return true;
|
||||
}
|
||||
|
||||
ue_ctx_t*
|
||||
s1ap::find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id)
|
||||
{
|
||||
|
@ -426,21 +447,34 @@ s1ap::find_ue_ctx_from_imsi(uint64_t imsi)
|
|||
}
|
||||
|
||||
void
|
||||
s1ap::release_ues_ecm_ctx_in_enb(uint16_t enb_id)
|
||||
s1ap::release_ues_ecm_ctx_in_enb(int32_t enb_assoc)
|
||||
{
|
||||
m_s1ap_log->console("Releasing UEs context\n");
|
||||
//delete UEs ctx
|
||||
std::map<uint16_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id);
|
||||
std::map<int32_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc);
|
||||
std::set<uint32_t>::iterator ue_id = ues_in_enb->second.begin();
|
||||
while(ue_id != ues_in_enb->second.end() )
|
||||
if(ue_id == ues_in_enb->second.end())
|
||||
{
|
||||
std::map<uint32_t, ue_ctx_t*>::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ctx.find(*ue_id);
|
||||
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->second->ecm_ctx;
|
||||
m_s1ap_log->info("Releasing UE ECM context. UE-MME S1AP Id: %d\n", ecm_ctx->mme_ue_s1ap_id);
|
||||
m_s1ap_log->console("Releasing UE ECM context. UE-MME S1AP Id: %d\n", ecm_ctx->mme_ue_s1ap_id);
|
||||
ues_in_enb->second.erase(ecm_ctx->mme_ue_s1ap_id);
|
||||
ecm_ctx->state = ECM_STATE_IDLE;
|
||||
ecm_ctx->mme_ue_s1ap_id = 0;
|
||||
ecm_ctx->enb_ue_s1ap_id = 0;
|
||||
m_s1ap_log->console("No UEs to be released\n");
|
||||
} else {
|
||||
while(ue_id != ues_in_enb->second.end() )
|
||||
{
|
||||
std::map<uint32_t, ue_ctx_t*>::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ctx.find(*ue_id);
|
||||
ue_emm_ctx_t *emm_ctx = &ue_ctx->second->emm_ctx;
|
||||
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->second->ecm_ctx;
|
||||
|
||||
m_s1ap_log->info("Releasing UE context. IMSI: %015lu, UE-MME S1AP Id: %d\n", emm_ctx->imsi, ecm_ctx->mme_ue_s1ap_id);
|
||||
if(emm_ctx->state == EMM_STATE_REGISTERED)
|
||||
{
|
||||
m_mme_gtpc->send_delete_session_request(emm_ctx->imsi);
|
||||
emm_ctx->state = EMM_STATE_DEREGISTERED;
|
||||
}
|
||||
m_s1ap_log->console("Releasing UE ECM context. UE-MME S1AP Id: %d\n", ecm_ctx->mme_ue_s1ap_id);
|
||||
ecm_ctx->state = ECM_STATE_IDLE;
|
||||
ecm_ctx->mme_ue_s1ap_id = 0;
|
||||
ecm_ctx->enb_ue_s1ap_id = 0;
|
||||
ues_in_enb->second.erase(ue_id++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,8 +497,8 @@ s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id)
|
|||
return false;
|
||||
}
|
||||
uint16_t enb_id = it->second;
|
||||
std::map<uint16_t,std::set<uint32_t> >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id);
|
||||
if(ue_set == m_enb_id_to_ue_ids.end())
|
||||
std::map<int32_t,std::set<uint32_t> >::iterator ue_set = m_enb_assoc_to_ue_ids.find(ecm_ctx->enb_sri.sinfo_assoc_id);
|
||||
if(ue_set == m_enb_assoc_to_ue_ids.end())
|
||||
{
|
||||
m_s1ap_log->error("Could not find the eNB's UEs.\n");
|
||||
return false;
|
||||
|
|
|
@ -372,7 +372,7 @@ s1ap_nas_transport::handle_nas_attach_request(uint32_t enb_ue_s1ap_id,
|
|||
|
||||
//Get attach type from attach request
|
||||
if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI)
|
||||
{
|
||||
{
|
||||
m_s1ap_log->console("Attach Request -- IMSI-style attach request\n");
|
||||
m_s1ap_log->info("Attach Request -- IMSI-style attach request\n");
|
||||
handle_nas_imsi_attach_request(enb_ue_s1ap_id, attach_req, pdn_con_req, reply_buffer, reply_flag, enb_sri);
|
||||
|
@ -514,6 +514,7 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id,
|
|||
memcpy(new_ctx,&ue_ctx,sizeof(ue_ctx_t));
|
||||
m_s1ap->add_ue_ctx_to_imsi_map(new_ctx);
|
||||
m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(new_ctx);
|
||||
m_s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id);
|
||||
|
||||
//Pack NAS Authentication Request in Downlink NAS Transport msg
|
||||
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand);
|
||||
|
@ -626,6 +627,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
ue_ctx_t *new_ctx = new ue_ctx_t;
|
||||
memcpy(new_ctx,&ue_ctx,sizeof(ue_ctx_t));
|
||||
m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(new_ctx);
|
||||
m_s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id);
|
||||
|
||||
pack_identity_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id);
|
||||
*reply_flag = true;
|
||||
|
@ -675,6 +677,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
|
||||
//Store context based on MME UE S1AP id
|
||||
m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx);
|
||||
m_s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id);
|
||||
|
||||
//Re-generate K_eNB
|
||||
srslte::security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb);
|
||||
|
|
|
@ -162,6 +162,7 @@ private:
|
|||
srslte_ue_ul_t ue_ul;
|
||||
srslte_timestamp_t tx_time;
|
||||
srslte_uci_data_t uci_data;
|
||||
srslte_cqi_value_t cqi_report;
|
||||
uint16_t ul_rnti;
|
||||
|
||||
// UL configuration parameters
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "phy/phy.h"
|
||||
#include "upper/usim.h"
|
||||
#include "upper/rrc.h"
|
||||
#include "upper/nas.h"
|
||||
#include "srslte/interfaces/ue_interfaces.h"
|
||||
|
||||
#include "srslte/common/logger.h"
|
||||
|
@ -129,9 +130,7 @@ typedef struct {
|
|||
usim_args_t usim;
|
||||
rrc_args_t rrc;
|
||||
std::string ue_category_str;
|
||||
std::string apn_name;
|
||||
std::string apn_user;
|
||||
std::string apn_pass;
|
||||
nas_args_t nas;
|
||||
expert_args_t expert;
|
||||
}all_args_t;
|
||||
|
||||
|
|
|
@ -39,6 +39,13 @@ using srslte::byte_buffer_t;
|
|||
|
||||
namespace srsue {
|
||||
|
||||
typedef struct {
|
||||
std::string apn_name;
|
||||
std::string apn_user;
|
||||
std::string apn_pass;
|
||||
bool force_imsi_attach;
|
||||
} nas_args_t;
|
||||
|
||||
// EMM states (3GPP 24.302 v10.0.0)
|
||||
typedef enum {
|
||||
EMM_STATE_NULL = 0,
|
||||
|
|
|
@ -84,9 +84,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
"UECapabilityInformation message. Default 0xe6041000")
|
||||
("rrc.ue_category", bpo::value<string>(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)")
|
||||
|
||||
("nas.apn", bpo::value<string>(&args->apn_name)->default_value(""), "Set Access Point Name (APN) for data services")
|
||||
("nas.user", bpo::value<string>(&args->apn_user)->default_value(""), "Username for CHAP authentication")
|
||||
("nas.pass", bpo::value<string>(&args->apn_pass)->default_value(""), "Password for CHAP authentication")
|
||||
("nas.apn", bpo::value<string>(&args->nas.apn_name)->default_value(""), "Set Access Point Name (APN) for data services")
|
||||
("nas.user", bpo::value<string>(&args->nas.apn_user)->default_value(""), "Username for CHAP authentication")
|
||||
("nas.pass", bpo::value<string>(&args->nas.apn_pass)->default_value(""), "Password for CHAP authentication")
|
||||
("nas.force_imsi_attach", bpo::value<bool>(&args->nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach")
|
||||
|
||||
|
||||
("pcap.enable", bpo::value<bool>(&args->pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark")
|
||||
("pcap.filename", bpo::value<string>(&args->pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename")
|
||||
|
|
|
@ -1032,7 +1032,8 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
|
|||
|
||||
void phch_worker::reset_uci()
|
||||
{
|
||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||
ZERO_OBJECT(uci_data);
|
||||
ZERO_OBJECT(cqi_report);
|
||||
}
|
||||
|
||||
void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS])
|
||||
|
@ -1082,7 +1083,6 @@ void phch_worker::set_uci_periodic_cqi()
|
|||
compute_ri(NULL, NULL, NULL);
|
||||
phy->last_pmi = (uint8_t) ue_dl.pmi[phy->last_ri % SRSLTE_MAX_LAYERS];
|
||||
|
||||
srslte_cqi_value_t cqi_report;
|
||||
ZERO_OBJECT(cqi_report);
|
||||
|
||||
if (period_cqi.format_is_subband) {
|
||||
|
@ -1110,6 +1110,8 @@ void phch_worker::set_uci_periodic_cqi()
|
|||
Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db_cqi);
|
||||
}
|
||||
uci_data.uci_cqi_len = (uint32_t) srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
|
||||
uci_data.uci_ri = phy->last_ri;
|
||||
uci_data.uci_ri_len = 0;
|
||||
rar_cqi_request = false;
|
||||
}
|
||||
}
|
||||
|
@ -1135,7 +1137,6 @@ void phch_worker::set_uci_aperiodic_cqi()
|
|||
reported RI. For other transmission modes they are reported conditioned on rank 1.
|
||||
*/
|
||||
if (rnti_is_set) {
|
||||
srslte_cqi_value_t cqi_report;
|
||||
ZERO_OBJECT(cqi_report);
|
||||
|
||||
cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
|
||||
|
@ -1289,11 +1290,13 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
|
|||
#endif
|
||||
|
||||
char cqi_str[SRSLTE_CQI_STR_MAX_CHAR] = "";
|
||||
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, SRSLTE_CQI_STR_MAX_CHAR);
|
||||
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
|
||||
srslte_cqi_value_tostring(&cqi_report, cqi_str, SRSLTE_CQI_STR_MAX_CHAR);
|
||||
}
|
||||
|
||||
uint8_t dummy[2] = {0,0};
|
||||
log_h->info_hex(payload, grant->mcs.tbs/8,
|
||||
"PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d%s%s%s, cfo=%.1f KHz%s%s%s\n",
|
||||
"PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d%s%s%s, cfo=%.1f KHz%s%s\n",
|
||||
(tti + HARQ_DELAY_MS) % 10240,
|
||||
grant->n_prb[0], grant->n_prb[0] + grant->L_prb,
|
||||
grant->mcs.tbs / 8, grant->mcs.idx, rv,
|
||||
|
@ -1301,7 +1304,6 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
|
|||
uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "",
|
||||
uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
|
||||
cfo * 15, timestr,
|
||||
uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
|
||||
uci_data.uci_cqi_len > 0 ? cqi_str : "");
|
||||
|
||||
// Store metrics
|
||||
|
@ -1343,17 +1345,18 @@ void phch_worker::encode_pucch()
|
|||
float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len);
|
||||
float gain = set_power(tx_power);
|
||||
|
||||
char str_cqi[SRSLTE_CQI_STR_MAX_CHAR] = "";
|
||||
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, str_cqi, SRSLTE_CQI_STR_MAX_CHAR);
|
||||
char cqi_str[SRSLTE_CQI_STR_MAX_CHAR] = "";
|
||||
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
|
||||
srslte_cqi_value_tostring(&cqi_report, cqi_str, SRSLTE_CQI_STR_MAX_CHAR);
|
||||
}
|
||||
|
||||
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s%s%s%s, sr=%s, cfo=%.1f KHz%s\n",
|
||||
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s%s%s, sr=%s, cfo=%.1f KHz%s\n",
|
||||
(tti + 4) % 10240,
|
||||
ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
|
||||
uci_data.uci_ack_len > 0 ? (uci_data.uci_ack ? "1" : "0") : "no",
|
||||
uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "",
|
||||
uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
|
||||
uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
|
||||
uci_data.uci_cqi_len > 0 ? str_cqi : "",
|
||||
uci_data.uci_cqi_len > 0 ? cqi_str : "",
|
||||
uci_data.scheduling_request ? "yes" : "no",
|
||||
cfo * 15, timestr);
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ bool ue::init(all_args_t *args_) {
|
|||
rlc.init(&pdcp, &rrc, this, &rlc_log, &mac, 0 /* RB_ID_SRB0 */);
|
||||
pdcp.init(&rlc, &rrc, &gw, &pdcp_log, 0 /* RB_ID_SRB0 */, SECURITY_DIRECTION_UPLINK);
|
||||
|
||||
srslte_nas_config_t nas_cfg(1, args->apn_name, args->apn_user, args->apn_pass); /* RB_ID_SRB1 */
|
||||
srslte_nas_config_t nas_cfg(1, args->nas.apn_name, args->nas.apn_user, args->nas.apn_pass, args->nas.force_imsi_attach); /* RB_ID_SRB1 */
|
||||
nas.init(usim, &rrc, &gw, &nas_log, nas_cfg);
|
||||
gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */);
|
||||
gw.set_netmask(args->expert.ip_netmask);
|
||||
|
|
|
@ -1364,6 +1364,11 @@ bool nas::read_ctxt_file(nas_sec_ctxt *ctxt)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (cfg.force_imsi_attach) {
|
||||
nas_log->info("Skip reading context from file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.open(".ctxt", std::ios::in);
|
||||
if(file.is_open()) {
|
||||
if(!readvar(file, "m_tmsi=", &ctxt->guti.m_tmsi)) {return false;}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <iostream>
|
||||
#include "srsue/hdr/upper/usim.h"
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include <assert.h>
|
||||
|
||||
using namespace srsue;
|
||||
|
||||
|
@ -67,8 +68,6 @@ uint16 mnc = 93;
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
srslte::log_filter usim_log("USIM");
|
||||
usim_log.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
usim_log.set_hex_limit(100000);
|
||||
bool net_valid;
|
||||
uint8_t res[16];
|
||||
int res_len;
|
||||
|
@ -79,18 +78,11 @@ int main(int argc, char **argv)
|
|||
args.imei = "356092040793011";
|
||||
args.imsi = "208930000000001";
|
||||
args.k = "8BAF473F2F8FD09487CCCBD7097C6862";
|
||||
args.using_op = false;
|
||||
args.opc = "8e27b6af0e692e750f32667a3b14605d"; // OPc
|
||||
args.using_op = true;
|
||||
args.op = "11111111111111111111111111111111";
|
||||
|
||||
srsue::usim usim;
|
||||
usim.init(&args, &usim_log);
|
||||
|
||||
if (usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) != AUTH_OK) {
|
||||
printf("USIM test failed.\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
printf("USIM test ok.\n");
|
||||
|
||||
return 0;
|
||||
assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ file_max_size = -1
|
|||
#
|
||||
# mode: USIM mode (soft/pcsc)
|
||||
# algo: Authentication algorithm (xor/milenage)
|
||||
# opc: 128-bit Operator Ciphered Variant Algorithm Configuration Field (hex)
|
||||
# op: 128-bit Operator Variant Algorithm Configuration Field (hex)
|
||||
# k: 128-bit subscriber key (hex)
|
||||
# imsi: 15 digit International Mobile Subscriber Identity
|
||||
# imei: 15 digit International Mobile Station Equipment Identity
|
||||
|
@ -98,7 +98,7 @@ file_max_size = -1
|
|||
[usim]
|
||||
mode = soft
|
||||
algo = xor
|
||||
opc = 63BFA50EE6523365FF14C1F45F88737D
|
||||
op = 63BFA50EE6523365FF14C1F45F88737D
|
||||
k = 00112233445566778899aabbccddeeff
|
||||
imsi = 001010123456789
|
||||
imei = 353490069873319
|
||||
|
@ -119,11 +119,16 @@ imei = 353490069873319
|
|||
#####################################################################
|
||||
# NAS configuration
|
||||
#
|
||||
# apn: Set Access Point Name (APN)
|
||||
# apn: Set Access Point Name (APN)
|
||||
# user: Username for CHAP authentication
|
||||
# pass: Password for CHAP authentication
|
||||
# force_imsi_attach: Whether to always perform an IMSI
|
||||
#####################################################################
|
||||
[nas]
|
||||
# apn = internetinternet
|
||||
|
||||
#apn = internetinternet
|
||||
#user = srsuser
|
||||
#pass = srspass
|
||||
#force_imsi_attach = false
|
||||
|
||||
[gui]
|
||||
enable = false
|
||||
|
|
Loading…
Reference in New Issue